aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-11-11 12:22:27 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-11 12:22:27 -0500
commit9b80b11c3faa460cf42904a1e368bf2cd075aff6 (patch)
treeecc349bbb90856c97be1b93cc9595ceea82fe2c5
parentb0b7b8eac33dc0f58ce9e7b7a61cf6529ee0b38c (diff)
parent271c3f35bd36613513e2c2cc90dc914a84df116e (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
-rw-r--r--arch/powerpc/Kconfig11
-rw-r--r--arch/powerpc/kernel/Makefile10
-rw-r--r--arch/powerpc/kernel/asm-offsets.c45
-rw-r--r--arch/powerpc/kernel/head_32.S1
-rw-r--r--arch/powerpc/kernel/lparcfg.c23
-rw-r--r--arch/powerpc/kernel/paca.c7
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c4
-rw-r--r--arch/powerpc/kernel/rtas-proc.c1
-rw-r--r--arch/powerpc/kernel/setup-common.c8
-rw-r--r--arch/powerpc/kernel/setup_64.c62
-rw-r--r--arch/powerpc/kernel/signal_32.c12
-rw-r--r--arch/powerpc/kernel/smp.c4
-rw-r--r--arch/powerpc/kernel/sysfs.c1
-rw-r--r--arch/powerpc/kernel/time.c40
-rw-r--r--arch/powerpc/kernel/traps.c1
-rw-r--r--arch/powerpc/kernel/udbg.c (renamed from arch/ppc64/kernel/udbg.c)0
-rw-r--r--arch/powerpc/kernel/udbg_16550.c (renamed from arch/ppc64/kernel/udbg_16550.c)0
-rw-r--r--arch/powerpc/kernel/udbg_scc.c (renamed from arch/ppc64/kernel/udbg_scc.c)0
-rw-r--r--arch/powerpc/kernel/vdso.c746
-rw-r--r--arch/powerpc/kernel/vdso32/Makefile (renamed from arch/ppc64/kernel/vdso32/Makefile)6
-rw-r--r--arch/powerpc/kernel/vdso32/cacheflush.S (renamed from arch/ppc64/kernel/vdso32/cacheflush.S)0
-rw-r--r--arch/powerpc/kernel/vdso32/datapage.S (renamed from arch/ppc64/kernel/vdso32/datapage.S)16
-rw-r--r--arch/powerpc/kernel/vdso32/gettimeofday.S315
-rw-r--r--arch/powerpc/kernel/vdso32/note.S (renamed from arch/ppc64/kernel/vdso32/note.S)0
-rw-r--r--arch/powerpc/kernel/vdso32/sigtramp.S (renamed from arch/ppc64/kernel/vdso32/sigtramp.S)0
-rw-r--r--arch/powerpc/kernel/vdso32/vdso32.lds.S (renamed from arch/ppc64/kernel/vdso32/vdso32.lds.S)5
-rw-r--r--arch/powerpc/kernel/vdso32/vdso32_wrapper.S (renamed from arch/ppc64/kernel/vdso32/vdso32_wrapper.S)2
-rw-r--r--arch/powerpc/kernel/vdso64/Makefile (renamed from arch/ppc64/kernel/vdso64/Makefile)0
-rw-r--r--arch/powerpc/kernel/vdso64/cacheflush.S (renamed from arch/ppc64/kernel/vdso64/cacheflush.S)0
-rw-r--r--arch/powerpc/kernel/vdso64/datapage.S (renamed from arch/ppc64/kernel/vdso64/datapage.S)16
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S242
-rw-r--r--arch/powerpc/kernel/vdso64/note.S (renamed from arch/ppc64/kernel/vdso64/note.S)0
-rw-r--r--arch/powerpc/kernel/vdso64/sigtramp.S (renamed from arch/ppc64/kernel/vdso64/sigtramp.S)0
-rw-r--r--arch/powerpc/kernel/vdso64/vdso64.lds.S (renamed from arch/ppc64/kernel/vdso64/vdso64.lds.S)5
-rw-r--r--arch/powerpc/kernel/vdso64/vdso64_wrapper.S (renamed from arch/ppc64/kernel/vdso64/vdso64_wrapper.S)2
-rw-r--r--arch/powerpc/mm/mem.c4
-rw-r--r--arch/powerpc/mm/numa.c369
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c1
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c1
-rw-r--r--arch/powerpc/platforms/pseries/setup.c4
-rw-r--r--arch/powerpc/platforms/pseries/smp.c4
-rw-r--r--arch/powerpc/xmon/xmon.c25
-rw-r--r--arch/ppc/kernel/asm-offsets.c28
-rw-r--r--arch/ppc/syslib/cpm2_pic.c2
-rw-r--r--arch/ppc64/Kconfig11
-rw-r--r--arch/ppc64/kernel/Makefile10
-rw-r--r--arch/ppc64/kernel/misc.S3
-rw-r--r--arch/ppc64/kernel/vdso32/gettimeofday.S140
-rw-r--r--arch/ppc64/kernel/vdso64/gettimeofday.S91
-rw-r--r--include/asm-powerpc/auxvec.h2
-rw-r--r--include/asm-powerpc/elf.h10
-rw-r--r--include/asm-powerpc/irq.h1
-rw-r--r--include/asm-powerpc/processor.h2
-rw-r--r--include/asm-powerpc/sparsemem.h4
-rw-r--r--include/asm-powerpc/systemcfg.h64
-rw-r--r--include/asm-powerpc/topology.h12
-rw-r--r--include/asm-powerpc/udbg.h (renamed from include/asm-ppc64/udbg.h)14
-rw-r--r--include/asm-powerpc/vdso.h (renamed from include/asm-ppc64/vdso.h)0
-rw-r--r--include/asm-powerpc/vdso_datapage.h108
-rw-r--r--include/asm-ppc/page.h8
-rw-r--r--include/asm-ppc64/mmzone.h69
-rw-r--r--include/asm-ppc64/page.h5
62 files changed, 1790 insertions, 787 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ed31062029f7..c523029674e6 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -581,17 +581,12 @@ config ARCH_FLATMEM_ENABLE
581 def_bool y 581 def_bool y
582 depends on PPC64 && !NUMA 582 depends on PPC64 && !NUMA
583 583
584config ARCH_DISCONTIGMEM_ENABLE 584config ARCH_SPARSEMEM_ENABLE
585 def_bool y
586 depends on SMP && PPC_PSERIES
587
588config ARCH_DISCONTIGMEM_DEFAULT
589 def_bool y 585 def_bool y
590 depends on ARCH_DISCONTIGMEM_ENABLE
591 586
592config ARCH_SPARSEMEM_ENABLE 587config ARCH_SPARSEMEM_DEFAULT
593 def_bool y 588 def_bool y
594 depends on ARCH_DISCONTIGMEM_ENABLE 589 depends on SMP && PPC_PSERIES
595 590
596source "mm/Kconfig" 591source "mm/Kconfig"
597 592
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c04bbd320594..9a74b7ab03a4 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,11 +12,13 @@ CFLAGS_btext.o += -fPIC
12endif 12endif
13 13
14obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ 14obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
15 irq.o signal_32.o pmc.o 15 irq.o signal_32.o pmc.o vdso.o
16obj-y += vdso32/
16obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
17 signal_64.o ptrace32.o systbl.o \ 18 signal_64.o ptrace32.o systbl.o \
18 paca.o ioctl32.o cpu_setup_power4.o \ 19 paca.o ioctl32.o cpu_setup_power4.o \
19 firmware.o sysfs.o 20 firmware.o sysfs.o udbg.o
21obj-$(CONFIG_PPC64) += vdso64/
20obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
21obj-$(CONFIG_POWER4) += idle_power4.o 23obj-$(CONFIG_POWER4) += idle_power4.o
22obj-$(CONFIG_PPC_OF) += of_device.o 24obj-$(CONFIG_PPC_OF) += of_device.o
@@ -29,6 +31,10 @@ obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
29obj-$(CONFIG_LPARCFG) += lparcfg.o 31obj-$(CONFIG_LPARCFG) += lparcfg.o
30obj-$(CONFIG_IBMVIO) += vio.o 32obj-$(CONFIG_IBMVIO) += vio.o
31obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 33obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
34obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
35obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
36udbgscc-$(CONFIG_PPC64) := udbg_scc.o
37obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y)
32 38
33ifeq ($(CONFIG_PPC_MERGE),y) 39ifeq ($(CONFIG_PPC_MERGE),y)
34 40
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8793102711a8..4550eb4f4fbd 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -37,12 +37,12 @@
37#include <asm/cputable.h> 37#include <asm/cputable.h>
38#include <asm/thread_info.h> 38#include <asm/thread_info.h>
39#include <asm/rtas.h> 39#include <asm/rtas.h>
40#include <asm/vdso_datapage.h>
40#ifdef CONFIG_PPC64 41#ifdef CONFIG_PPC64
41#include <asm/paca.h> 42#include <asm/paca.h>
42#include <asm/lppaca.h> 43#include <asm/lppaca.h>
43#include <asm/iseries/hv_lp_event.h> 44#include <asm/iseries/hv_lp_event.h>
44#include <asm/cache.h> 45#include <asm/cache.h>
45#include <asm/systemcfg.h>
46#include <asm/compat.h> 46#include <asm/compat.h>
47#endif 47#endif
48 48
@@ -251,25 +251,42 @@ int main(void)
251 251
252 DEFINE(TASK_SIZE, TASK_SIZE); 252 DEFINE(TASK_SIZE, TASK_SIZE);
253 DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); 253 DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
254#else /* CONFIG_PPC64 */ 254#endif /* ! CONFIG_PPC64 */
255 /* systemcfg offsets for use by vdso */
256 DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp));
257 DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec));
258 DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs));
259 DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec));
260 DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count));
261 DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest));
262 DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime));
263 DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32));
264 DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64));
265 255
266 /* timeval/timezone offsets for use by vdso */ 256 /* datapage offsets for use by vdso */
257 DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct vdso_data, tb_orig_stamp));
258 DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct vdso_data, tb_ticks_per_sec));
259 DEFINE(CFG_TB_TO_XS, offsetof(struct vdso_data, tb_to_xs));
260 DEFINE(CFG_STAMP_XSEC, offsetof(struct vdso_data, stamp_xsec));
261 DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct vdso_data, tb_update_count));
262 DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct vdso_data, tz_minuteswest));
263 DEFINE(CFG_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
264 DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
265 DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
266 DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
267#ifdef CONFIG_PPC64
268 DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64));
267 DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec)); 269 DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
268 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); 270 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
269 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); 271 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
270 DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); 272 DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
273 DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec));
274 DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec));
275#else
276 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec));
277 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec));
278 DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec));
279 DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec));
280#endif
281 /* timeval/timezone offsets for use by vdso */
271 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); 282 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
272 DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); 283 DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
273#endif /* CONFIG_PPC64 */ 284
285 /* Other bits used by the vdso */
286 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
287 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
288 DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
289 DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
290
274 return 0; 291 return 0;
275} 292}
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index b102e3a2415e..ccdf94731e30 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -1100,6 +1100,7 @@ start_here:
1100 mr r3,r31 1100 mr r3,r31
1101 mr r4,r30 1101 mr r4,r30
1102 bl machine_init 1102 bl machine_init
1103 bl __save_cpu_setup
1103 bl MMU_init 1104 bl MMU_init
1104 1105
1105#ifdef CONFIG_APUS 1106#ifdef CONFIG_APUS
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 5e954fae031f..1b3ba8a440a6 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -35,7 +35,7 @@
35#include <asm/time.h> 35#include <asm/time.h>
36#include <asm/iseries/it_exp_vpd_panel.h> 36#include <asm/iseries/it_exp_vpd_panel.h>
37#include <asm/prom.h> 37#include <asm/prom.h>
38#include <asm/systemcfg.h> 38#include <asm/vdso_datapage.h>
39 39
40#define MODULE_VERS "1.6" 40#define MODULE_VERS "1.6"
41#define MODULE_NAME "lparcfg" 41#define MODULE_NAME "lparcfg"
@@ -43,7 +43,7 @@
43/* #define LPARCFG_DEBUG */ 43/* #define LPARCFG_DEBUG */
44 44
45/* find a better place for this function... */ 45/* find a better place for this function... */
46void log_plpar_hcall_return(unsigned long rc, char *tag) 46static void log_plpar_hcall_return(unsigned long rc, char *tag)
47{ 47{
48 if (rc == 0) /* success, return */ 48 if (rc == 0) /* success, return */
49 return; 49 return;
@@ -213,11 +213,10 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
213 unsigned long dummy; 213 unsigned long dummy;
214 rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy); 214 rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
215 215
216 log_plpar_hcall_return(rc, "H_PIC"); 216 if (rc != H_Authority)
217 log_plpar_hcall_return(rc, "H_PIC");
217} 218}
218 219
219static unsigned long get_purr(void);
220
221/* Track sum of all purrs across all processors. This is used to further */ 220/* Track sum of all purrs across all processors. This is used to further */
222/* calculate usage values by different applications */ 221/* calculate usage values by different applications */
223 222
@@ -319,8 +318,6 @@ static void parse_system_parameter_string(struct seq_file *m)
319 kfree(local_buffer); 318 kfree(local_buffer);
320} 319}
321 320
322static int lparcfg_count_active_processors(void);
323
324/* Return the number of processors in the system. 321/* Return the number of processors in the system.
325 * This function reads through the device tree and counts 322 * This function reads through the device tree and counts
326 * the virtual processors, this does not include threads. 323 * the virtual processors, this does not include threads.
@@ -372,7 +369,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
372 lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); 369 lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);
373 370
374 if (lrdrp == NULL) { 371 if (lrdrp == NULL) {
375 partition_potential_processors = _systemcfg->processorCount; 372 partition_potential_processors = vdso_data->processorCount;
376 } else { 373 } else {
377 partition_potential_processors = *(lrdrp + 4); 374 partition_potential_processors = *(lrdrp + 4);
378 } 375 }
@@ -548,7 +545,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
548 retval = -EIO; 545 retval = -EIO;
549 } 546 }
550 547
551 out: 548out:
552 kfree(kbuf); 549 kfree(kbuf);
553 return retval; 550 return retval;
554} 551}
@@ -561,10 +558,10 @@ static int lparcfg_open(struct inode *inode, struct file *file)
561} 558}
562 559
563struct file_operations lparcfg_fops = { 560struct file_operations lparcfg_fops = {
564 .owner = THIS_MODULE, 561 .owner = THIS_MODULE,
565 .read = seq_read, 562 .read = seq_read,
566 .open = lparcfg_open, 563 .open = lparcfg_open,
567 .release = single_release, 564 .release = single_release,
568}; 565};
569 566
570int __init lparcfg_init(void) 567int __init lparcfg_init(void)
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 3cf2517c5f91..a7b68f911eb1 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -15,17 +15,10 @@
15#include <asm/processor.h> 15#include <asm/processor.h>
16#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/page.h> 17#include <asm/page.h>
18#include <asm/systemcfg.h>
19#include <asm/lppaca.h> 18#include <asm/lppaca.h>
20#include <asm/iseries/it_lp_queue.h> 19#include <asm/iseries/it_lp_queue.h>
21#include <asm/paca.h> 20#include <asm/paca.h>
22 21
23static union {
24 struct systemcfg data;
25 u8 page[PAGE_SIZE];
26} systemcfg_store __attribute__((__section__(".data.page.aligned")));
27struct systemcfg *_systemcfg = &systemcfg_store.data;
28
29 22
30/* This symbol is provided by the linker - let it fill in the paca 23/* This symbol is provided by the linker - let it fill in the paca
31 * field correctly */ 24 * field correctly */
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index a1c19502fe8b..7ba42a405f41 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -23,7 +23,7 @@
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25 25
26#include <asm/systemcfg.h> 26#include <asm/vdso_datapage.h>
27#include <asm/rtas.h> 27#include <asm/rtas.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/prom.h> 29#include <asm/prom.h>
@@ -72,7 +72,7 @@ static int __init proc_ppc64_init(void)
72 if (!pde) 72 if (!pde)
73 return 1; 73 return 1;
74 pde->nlink = 1; 74 pde->nlink = 1;
75 pde->data = _systemcfg; 75 pde->data = vdso_data;
76 pde->size = PAGE_SIZE; 76 pde->size = PAGE_SIZE;
77 pde->proc_fops = &page_map_fops; 77 pde->proc_fops = &page_map_fops;
78 78
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index ae1a36449ccd..7a95b8a28354 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -32,7 +32,6 @@
32#include <asm/rtas.h> 32#include <asm/rtas.h>
33#include <asm/machdep.h> /* for ppc_md */ 33#include <asm/machdep.h> /* for ppc_md */
34#include <asm/time.h> 34#include <asm/time.h>
35#include <asm/systemcfg.h>
36 35
37/* Token for Sensors */ 36/* Token for Sensors */
38#define KEY_SWITCH 0x0001 37#define KEY_SWITCH 0x0001
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index bae4bff138f1..33e7f2c7f194 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -33,7 +33,7 @@
33#include <asm/io.h> 33#include <asm/io.h>
34#include <asm/prom.h> 34#include <asm/prom.h>
35#include <asm/processor.h> 35#include <asm/processor.h>
36#include <asm/systemcfg.h> 36#include <asm/vdso_datapage.h>
37#include <asm/pgtable.h> 37#include <asm/pgtable.h>
38#include <asm/smp.h> 38#include <asm/smp.h>
39#include <asm/elf.h> 39#include <asm/elf.h>
@@ -444,10 +444,8 @@ void __init check_for_initrd(void)
444 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && 444 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
445 initrd_end > initrd_start) 445 initrd_end > initrd_start)
446 ROOT_DEV = Root_RAM0; 446 ROOT_DEV = Root_RAM0;
447 else { 447 else
448 printk("Bogus initrd %08lx %08lx\n", initrd_start, initrd_end);
449 initrd_start = initrd_end = 0; 448 initrd_start = initrd_end = 0;
450 }
451 449
452 if (initrd_start) 450 if (initrd_start)
453 printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end); 451 printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end);
@@ -566,7 +564,7 @@ void __init smp_setup_cpu_maps(void)
566 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); 564 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
567 } 565 }
568 566
569 _systemcfg->processorCount = num_present_cpus(); 567 vdso_data->processorCount = num_present_cpus();
570#endif /* CONFIG_PPC64 */ 568#endif /* CONFIG_PPC64 */
571} 569}
572#endif /* CONFIG_SMP */ 570#endif /* CONFIG_SMP */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6791668213e7..fdbd9f9122f2 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -57,7 +57,6 @@
57#include <asm/lmb.h> 57#include <asm/lmb.h>
58#include <asm/iseries/it_lp_naca.h> 58#include <asm/iseries/it_lp_naca.h>
59#include <asm/firmware.h> 59#include <asm/firmware.h>
60#include <asm/systemcfg.h>
61#include <asm/xmon.h> 60#include <asm/xmon.h>
62#include <asm/udbg.h> 61#include <asm/udbg.h>
63 62
@@ -375,9 +374,8 @@ static void __init initialize_cache_info(void)
375 DBG("Argh, can't find dcache properties ! " 374 DBG("Argh, can't find dcache properties ! "
376 "sizep: %p, lsizep: %p\n", sizep, lsizep); 375 "sizep: %p, lsizep: %p\n", sizep, lsizep);
377 376
378 _systemcfg->dcache_size = ppc64_caches.dsize = size; 377 ppc64_caches.dsize = size;
379 _systemcfg->dcache_line_size = 378 ppc64_caches.dline_size = lsize;
380 ppc64_caches.dline_size = lsize;
381 ppc64_caches.log_dline_size = __ilog2(lsize); 379 ppc64_caches.log_dline_size = __ilog2(lsize);
382 ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; 380 ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
383 381
@@ -393,22 +391,13 @@ static void __init initialize_cache_info(void)
393 DBG("Argh, can't find icache properties ! " 391 DBG("Argh, can't find icache properties ! "
394 "sizep: %p, lsizep: %p\n", sizep, lsizep); 392 "sizep: %p, lsizep: %p\n", sizep, lsizep);
395 393
396 _systemcfg->icache_size = ppc64_caches.isize = size; 394 ppc64_caches.isize = size;
397 _systemcfg->icache_line_size = 395 ppc64_caches.iline_size = lsize;
398 ppc64_caches.iline_size = lsize;
399 ppc64_caches.log_iline_size = __ilog2(lsize); 396 ppc64_caches.log_iline_size = __ilog2(lsize);
400 ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; 397 ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
401 } 398 }
402 } 399 }
403 400
404 /* Add an eye catcher and the systemcfg layout version number */
405 strcpy(_systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
406 _systemcfg->version.major = SYSTEMCFG_MAJOR;
407 _systemcfg->version.minor = SYSTEMCFG_MINOR;
408 _systemcfg->processor = mfspr(SPRN_PVR);
409 _systemcfg->platform = _machine;
410 _systemcfg->physicalMemorySize = lmb_phys_mem_size();
411
412 DBG(" <- initialize_cache_info()\n"); 401 DBG(" <- initialize_cache_info()\n");
413} 402}
414 403
@@ -495,15 +484,14 @@ void __init setup_system(void)
495 484
496 printk("-----------------------------------------------------\n"); 485 printk("-----------------------------------------------------\n");
497 printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); 486 printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
498 printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); 487 printk("ppc64_interrupt_controller = 0x%ld\n",
499 printk("systemcfg = 0x%p\n", _systemcfg); 488 ppc64_interrupt_controller);
500 printk("systemcfg->platform = 0x%x\n", _systemcfg->platform); 489 printk("platform = 0x%x\n", _machine);
501 printk("systemcfg->processorCount = 0x%lx\n", _systemcfg->processorCount); 490 printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size());
502 printk("systemcfg->physicalMemorySize = 0x%lx\n", _systemcfg->physicalMemorySize);
503 printk("ppc64_caches.dcache_line_size = 0x%x\n", 491 printk("ppc64_caches.dcache_line_size = 0x%x\n",
504 ppc64_caches.dline_size); 492 ppc64_caches.dline_size);
505 printk("ppc64_caches.icache_line_size = 0x%x\n", 493 printk("ppc64_caches.icache_line_size = 0x%x\n",
506 ppc64_caches.iline_size); 494 ppc64_caches.iline_size);
507 printk("htab_address = 0x%p\n", htab_address); 495 printk("htab_address = 0x%p\n", htab_address);
508 printk("htab_hash_mask = 0x%lx\n", htab_hash_mask); 496 printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
509 printk("-----------------------------------------------------\n"); 497 printk("-----------------------------------------------------\n");
@@ -568,33 +556,6 @@ static void __init emergency_stack_init(void)
568} 556}
569 557
570/* 558/*
571 * Called from setup_arch to initialize the bitmap of available
572 * syscalls in the systemcfg page
573 */
574void __init setup_syscall_map(void)
575{
576 unsigned int i, count64 = 0, count32 = 0;
577 extern unsigned long *sys_call_table;
578 extern unsigned long sys_ni_syscall;
579
580
581 for (i = 0; i < __NR_syscalls; i++) {
582 if (sys_call_table[i*2] != sys_ni_syscall) {
583 count64++;
584 _systemcfg->syscall_map_64[i >> 5] |=
585 0x80000000UL >> (i & 0x1f);
586 }
587 if (sys_call_table[i*2+1] != sys_ni_syscall) {
588 count32++;
589 _systemcfg->syscall_map_32[i >> 5] |=
590 0x80000000UL >> (i & 0x1f);
591 }
592 }
593 printk(KERN_INFO "Syscall map setup, %d 32-bit and %d 64-bit syscalls\n",
594 count32, count64);
595}
596
597/*
598 * Called into from start_kernel, after lock_kernel has been called. 559 * Called into from start_kernel, after lock_kernel has been called.
599 * Initializes bootmem, which is unsed to manage page allocation until 560 * Initializes bootmem, which is unsed to manage page allocation until
600 * mem_init is called. 561 * mem_init is called.
@@ -635,9 +596,6 @@ void __init setup_arch(char **cmdline_p)
635 do_init_bootmem(); 596 do_init_bootmem();
636 sparse_init(); 597 sparse_init();
637 598
638 /* initialize the syscall map in systemcfg */
639 setup_syscall_map();
640
641#ifdef CONFIG_DUMMY_CONSOLE 599#ifdef CONFIG_DUMMY_CONSOLE
642 conswitchp = &dummy_con; 600 conswitchp = &dummy_con;
643#endif 601#endif
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index a7c4515f320f..8bdf95b7e420 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -43,10 +43,10 @@
43#include <asm/uaccess.h> 43#include <asm/uaccess.h>
44#include <asm/cacheflush.h> 44#include <asm/cacheflush.h>
45#include <asm/sigcontext.h> 45#include <asm/sigcontext.h>
46#include <asm/vdso.h>
46#ifdef CONFIG_PPC64 47#ifdef CONFIG_PPC64
47#include "ppc32.h" 48#include "ppc32.h"
48#include <asm/unistd.h> 49#include <asm/unistd.h>
49#include <asm/vdso.h>
50#else 50#else
51#include <asm/ucontext.h> 51#include <asm/ucontext.h>
52#include <asm/pgtable.h> 52#include <asm/pgtable.h>
@@ -809,14 +809,11 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
809 809
810 /* Save user registers on the stack */ 810 /* Save user registers on the stack */
811 frame = &rt_sf->uc.uc_mcontext; 811 frame = &rt_sf->uc.uc_mcontext;
812#ifdef CONFIG_PPC64
813 if (vdso32_rt_sigtramp && current->thread.vdso_base) { 812 if (vdso32_rt_sigtramp && current->thread.vdso_base) {
814 if (save_user_regs(regs, frame, 0)) 813 if (save_user_regs(regs, frame, 0))
815 goto badframe; 814 goto badframe;
816 regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; 815 regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
817 } else 816 } else {
818#endif
819 {
820 if (save_user_regs(regs, frame, __NR_rt_sigreturn)) 817 if (save_user_regs(regs, frame, __NR_rt_sigreturn))
821 goto badframe; 818 goto badframe;
822 regs->link = (unsigned long) frame->tramp; 819 regs->link = (unsigned long) frame->tramp;
@@ -1090,14 +1087,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
1090 || __put_user(sig, &sc->signal)) 1087 || __put_user(sig, &sc->signal))
1091 goto badframe; 1088 goto badframe;
1092 1089
1093#ifdef CONFIG_PPC64
1094 if (vdso32_sigtramp && current->thread.vdso_base) { 1090 if (vdso32_sigtramp && current->thread.vdso_base) {
1095 if (save_user_regs(regs, &frame->mctx, 0)) 1091 if (save_user_regs(regs, &frame->mctx, 0))
1096 goto badframe; 1092 goto badframe;
1097 regs->link = current->thread.vdso_base + vdso32_sigtramp; 1093 regs->link = current->thread.vdso_base + vdso32_sigtramp;
1098 } else 1094 } else {
1099#endif
1100 {
1101 if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) 1095 if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
1102 goto badframe; 1096 goto badframe;
1103 regs->link = (unsigned long) frame->mctx.tramp; 1097 regs->link = (unsigned long) frame->mctx.tramp;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index e28a139c29d0..62dfc5b8d765 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -44,7 +44,7 @@
44#include <asm/cputable.h> 44#include <asm/cputable.h>
45#include <asm/system.h> 45#include <asm/system.h>
46#include <asm/mpic.h> 46#include <asm/mpic.h>
47#include <asm/systemcfg.h> 47#include <asm/vdso_datapage.h>
48#ifdef CONFIG_PPC64 48#ifdef CONFIG_PPC64
49#include <asm/paca.h> 49#include <asm/paca.h>
50#endif 50#endif
@@ -371,7 +371,7 @@ int generic_cpu_disable(void)
371 371
372 cpu_clear(cpu, cpu_online_map); 372 cpu_clear(cpu, cpu_online_map);
373#ifdef CONFIG_PPC64 373#ifdef CONFIG_PPC64
374 _systemcfg->processorCount--; 374 vdso_data->processorCount--;
375 fixup_irqs(cpu_online_map); 375 fixup_irqs(cpu_online_map);
376#endif 376#endif
377 return 0; 377 return 0;
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 850af198fb5f..0f0c3a9ae2e5 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -16,7 +16,6 @@
16#include <asm/firmware.h> 16#include <asm/firmware.h>
17#include <asm/hvcall.h> 17#include <asm/hvcall.h>
18#include <asm/prom.h> 18#include <asm/prom.h>
19#include <asm/systemcfg.h>
20#include <asm/paca.h> 19#include <asm/paca.h>
21#include <asm/lppaca.h> 20#include <asm/lppaca.h>
22#include <asm/machdep.h> 21#include <asm/machdep.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 260b6ecd26a9..070b4b458aaf 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -62,8 +62,8 @@
62#include <asm/irq.h> 62#include <asm/irq.h>
63#include <asm/div64.h> 63#include <asm/div64.h>
64#include <asm/smp.h> 64#include <asm/smp.h>
65#include <asm/vdso_datapage.h>
65#ifdef CONFIG_PPC64 66#ifdef CONFIG_PPC64
66#include <asm/systemcfg.h>
67#include <asm/firmware.h> 67#include <asm/firmware.h>
68#endif 68#endif
69#ifdef CONFIG_PPC_ISERIES 69#ifdef CONFIG_PPC_ISERIES
@@ -261,7 +261,6 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
261 do_gtod.varp = temp_varp; 261 do_gtod.varp = temp_varp;
262 do_gtod.var_idx = temp_idx; 262 do_gtod.var_idx = temp_idx;
263 263
264#ifdef CONFIG_PPC64
265 /* 264 /*
266 * tb_update_count is used to allow the userspace gettimeofday code 265 * tb_update_count is used to allow the userspace gettimeofday code
267 * to assure itself that it sees a consistent view of the tb_to_xs and 266 * to assure itself that it sees a consistent view of the tb_to_xs and
@@ -271,14 +270,15 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
271 * tb_to_xs and stamp_xsec values are consistent. If not, then it 270 * tb_to_xs and stamp_xsec values are consistent. If not, then it
272 * loops back and reads them again until this criteria is met. 271 * loops back and reads them again until this criteria is met.
273 */ 272 */
274 ++(_systemcfg->tb_update_count); 273 ++(vdso_data->tb_update_count);
275 smp_wmb(); 274 smp_wmb();
276 _systemcfg->tb_orig_stamp = new_tb_stamp; 275 vdso_data->tb_orig_stamp = new_tb_stamp;
277 _systemcfg->stamp_xsec = new_stamp_xsec; 276 vdso_data->stamp_xsec = new_stamp_xsec;
278 _systemcfg->tb_to_xs = new_tb_to_xs; 277 vdso_data->tb_to_xs = new_tb_to_xs;
278 vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
279 vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
279 smp_wmb(); 280 smp_wmb();
280 ++(_systemcfg->tb_update_count); 281 ++(vdso_data->tb_update_count);
281#endif
282} 282}
283 283
284/* 284/*
@@ -357,9 +357,8 @@ static void iSeries_tb_recal(void)
357 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; 357 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
358 tb_to_xs = divres.result_low; 358 tb_to_xs = divres.result_low;
359 do_gtod.varp->tb_to_xs = tb_to_xs; 359 do_gtod.varp->tb_to_xs = tb_to_xs;
360 _systemcfg->tb_ticks_per_sec = 360 vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
361 tb_ticks_per_sec; 361 vdso_data->tb_to_xs = tb_to_xs;
362 _systemcfg->tb_to_xs = tb_to_xs;
363 } 362 }
364 else { 363 else {
365 printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" 364 printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
@@ -561,10 +560,8 @@ int do_settimeofday(struct timespec *tv)
561 new_xsec += (u64)new_sec * XSEC_PER_SEC - tb_delta_xs; 560 new_xsec += (u64)new_sec * XSEC_PER_SEC - tb_delta_xs;
562 update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); 561 update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
563 562
564#ifdef CONFIG_PPC64 563 vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
565 _systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; 564 vdso_data->tz_dsttime = sys_tz.tz_dsttime;
566 _systemcfg->tz_dsttime = sys_tz.tz_dsttime;
567#endif
568 565
569 write_sequnlock_irqrestore(&xtime_lock, flags); 566 write_sequnlock_irqrestore(&xtime_lock, flags);
570 clock_was_set(); 567 clock_was_set();
@@ -713,13 +710,12 @@ void __init time_init(void)
713 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; 710 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
714 do_gtod.varp->tb_to_xs = tb_to_xs; 711 do_gtod.varp->tb_to_xs = tb_to_xs;
715 do_gtod.tb_to_us = tb_to_us; 712 do_gtod.tb_to_us = tb_to_us;
716#ifdef CONFIG_PPC64 713
717 _systemcfg->tb_orig_stamp = tb_last_jiffy; 714 vdso_data->tb_orig_stamp = tb_last_jiffy;
718 _systemcfg->tb_update_count = 0; 715 vdso_data->tb_update_count = 0;
719 _systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; 716 vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
720 _systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; 717 vdso_data->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
721 _systemcfg->tb_to_xs = tb_to_xs; 718 vdso_data->tb_to_xs = tb_to_xs;
722#endif
723 719
724 time_freq = 0; 720 time_freq = 0;
725 721
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2020bb7648fb..1511454c4690 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -49,7 +49,6 @@
49#ifdef CONFIG_PPC64 49#ifdef CONFIG_PPC64
50#include <asm/firmware.h> 50#include <asm/firmware.h>
51#include <asm/processor.h> 51#include <asm/processor.h>
52#include <asm/systemcfg.h>
53#endif 52#endif
54 53
55#ifdef CONFIG_PPC64 /* XXX */ 54#ifdef CONFIG_PPC64 /* XXX */
diff --git a/arch/ppc64/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 0d878e72fc44..0d878e72fc44 100644
--- a/arch/ppc64/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
diff --git a/arch/ppc64/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 9313574ab935..9313574ab935 100644
--- a/arch/ppc64/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
diff --git a/arch/ppc64/kernel/udbg_scc.c b/arch/powerpc/kernel/udbg_scc.c
index 820c53551507..820c53551507 100644
--- a/arch/ppc64/kernel/udbg_scc.c
+++ b/arch/powerpc/kernel/udbg_scc.c
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
new file mode 100644
index 000000000000..0d4d8bec0df4
--- /dev/null
+++ b/arch/powerpc/kernel/vdso.c
@@ -0,0 +1,746 @@
1/*
2 * linux/arch/ppc64/kernel/vdso.c
3 *
4 * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
5 * <benh@kernel.crashing.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/errno.h>
16#include <linux/sched.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/slab.h>
24#include <linux/user.h>
25#include <linux/elf.h>
26#include <linux/security.h>
27#include <linux/bootmem.h>
28
29#include <asm/pgtable.h>
30#include <asm/system.h>
31#include <asm/processor.h>
32#include <asm/mmu.h>
33#include <asm/mmu_context.h>
34#include <asm/lmb.h>
35#include <asm/machdep.h>
36#include <asm/cputable.h>
37#include <asm/sections.h>
38#include <asm/vdso.h>
39#include <asm/vdso_datapage.h>
40
41#undef DEBUG
42
43#ifdef DEBUG
44#define DBG(fmt...) printk(fmt)
45#else
46#define DBG(fmt...)
47#endif
48
49/* Max supported size for symbol names */
50#define MAX_SYMNAME 64
51
52extern char vdso32_start, vdso32_end;
53static void *vdso32_kbase = &vdso32_start;
54unsigned int vdso32_pages;
55unsigned long vdso32_sigtramp;
56unsigned long vdso32_rt_sigtramp;
57
58#ifdef CONFIG_PPC64
59extern char vdso64_start, vdso64_end;
60static void *vdso64_kbase = &vdso64_start;
61unsigned int vdso64_pages;
62unsigned long vdso64_rt_sigtramp;
63#endif /* CONFIG_PPC64 */
64
65/*
66 * The vdso data page (aka. systemcfg for old ppc64 fans) is here.
67 * Once the early boot kernel code no longer needs to muck around
68 * with it, it will become dynamically allocated
69 */
70static union {
71 struct vdso_data data;
72 u8 page[PAGE_SIZE];
73} vdso_data_store __attribute__((__section__(".data.page_aligned")));
74struct vdso_data *vdso_data = &vdso_data_store.data;
75
76/* Format of the patch table */
77struct vdso_patch_def
78{
79 unsigned long ftr_mask, ftr_value;
80 const char *gen_name;
81 const char *fix_name;
82};
83
84/* Table of functions to patch based on the CPU type/revision
85 *
86 * Currently, we only change sync_dicache to do nothing on processors
87 * with a coherent icache
88 */
89static struct vdso_patch_def vdso_patches[] = {
90 {
91 CPU_FTR_COHERENT_ICACHE, CPU_FTR_COHERENT_ICACHE,
92 "__kernel_sync_dicache", "__kernel_sync_dicache_p5"
93 },
94 {
95 CPU_FTR_USE_TB, 0,
96 "__kernel_gettimeofday", NULL
97 },
98};
99
100/*
101 * Some infos carried around for each of them during parsing at
102 * boot time.
103 */
104struct lib32_elfinfo
105{
106 Elf32_Ehdr *hdr; /* ptr to ELF */
107 Elf32_Sym *dynsym; /* ptr to .dynsym section */
108 unsigned long dynsymsize; /* size of .dynsym section */
109 char *dynstr; /* ptr to .dynstr section */
110 unsigned long text; /* offset of .text section in .so */
111};
112
113struct lib64_elfinfo
114{
115 Elf64_Ehdr *hdr;
116 Elf64_Sym *dynsym;
117 unsigned long dynsymsize;
118 char *dynstr;
119 unsigned long text;
120};
121
122
123#ifdef __DEBUG
124static void dump_one_vdso_page(struct page *pg, struct page *upg)
125{
126 printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT),
127 page_count(pg),
128 pg->flags);
129 if (upg/* && pg != upg*/) {
130 printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg)
131 << PAGE_SHIFT),
132 page_count(upg),
133 upg->flags);
134 }
135 printk("\n");
136}
137
138static void dump_vdso_pages(struct vm_area_struct * vma)
139{
140 int i;
141
142 if (!vma || test_thread_flag(TIF_32BIT)) {
143 printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase);
144 for (i=0; i<vdso32_pages; i++) {
145 struct page *pg = virt_to_page(vdso32_kbase +
146 i*PAGE_SIZE);
147 struct page *upg = (vma && vma->vm_mm) ?
148 follow_page(vma->vm_mm, vma->vm_start +
149 i*PAGE_SIZE, 0)
150 : NULL;
151 dump_one_vdso_page(pg, upg);
152 }
153 }
154 if (!vma || !test_thread_flag(TIF_32BIT)) {
155 printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase);
156 for (i=0; i<vdso64_pages; i++) {
157 struct page *pg = virt_to_page(vdso64_kbase +
158 i*PAGE_SIZE);
159 struct page *upg = (vma && vma->vm_mm) ?
160 follow_page(vma->vm_mm, vma->vm_start +
161 i*PAGE_SIZE, 0)
162 : NULL;
163 dump_one_vdso_page(pg, upg);
164 }
165 }
166}
167#endif /* DEBUG */
168
169/*
170 * Keep a dummy vma_close for now, it will prevent VMA merging.
171 */
172static void vdso_vma_close(struct vm_area_struct * vma)
173{
174}
175
176/*
177 * Our nopage() function, maps in the actual vDSO kernel pages, they will
178 * be mapped read-only by do_no_page(), and eventually COW'ed, either
179 * right away for an initial write access, or by do_wp_page().
180 */
181static struct page * vdso_vma_nopage(struct vm_area_struct * vma,
182 unsigned long address, int *type)
183{
184 unsigned long offset = address - vma->vm_start;
185 struct page *pg;
186#ifdef CONFIG_PPC64
187 void *vbase = test_thread_flag(TIF_32BIT) ?
188 vdso32_kbase : vdso64_kbase;
189#else
190 void *vbase = vdso32_kbase;
191#endif
192
193 DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n",
194 current->comm, address, offset);
195
196 if (address < vma->vm_start || address > vma->vm_end)
197 return NOPAGE_SIGBUS;
198
199 /*
200 * Last page is systemcfg.
201 */
202 if ((vma->vm_end - address) <= PAGE_SIZE)
203 pg = virt_to_page(vdso_data);
204 else
205 pg = virt_to_page(vbase + offset);
206
207 get_page(pg);
208 DBG(" ->page count: %d\n", page_count(pg));
209
210 return pg;
211}
212
213static struct vm_operations_struct vdso_vmops = {
214 .close = vdso_vma_close,
215 .nopage = vdso_vma_nopage,
216};
217
218/*
219 * This is called from binfmt_elf, we create the special vma for the
220 * vDSO and insert it into the mm struct tree
221 */
222int arch_setup_additional_pages(struct linux_binprm *bprm,
223 int executable_stack)
224{
225 struct mm_struct *mm = current->mm;
226 struct vm_area_struct *vma;
227 unsigned long vdso_pages;
228 unsigned long vdso_base;
229
230#ifdef CONFIG_PPC64
231 if (test_thread_flag(TIF_32BIT)) {
232 vdso_pages = vdso32_pages;
233 vdso_base = VDSO32_MBASE;
234 } else {
235 vdso_pages = vdso64_pages;
236 vdso_base = VDSO64_MBASE;
237 }
238#else
239 vdso_pages = vdso32_pages;
240 vdso_base = VDSO32_MBASE;
241#endif
242
243 current->thread.vdso_base = 0;
244
245 /* vDSO has a problem and was disabled, just don't "enable" it for the
246 * process
247 */
248 if (vdso_pages == 0)
249 return 0;
250
251 vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
252 if (vma == NULL)
253 return -ENOMEM;
254
255 memset(vma, 0, sizeof(*vma));
256
257 /* Add a page to the vdso size for the data page */
258 vdso_pages ++;
259
260 /*
261 * pick a base address for the vDSO in process space. We try to put it
262 * at vdso_base which is the "natural" base for it, but we might fail
263 * and end up putting it elsewhere.
264 */
265 vdso_base = get_unmapped_area(NULL, vdso_base,
266 vdso_pages << PAGE_SHIFT, 0, 0);
267 if (vdso_base & ~PAGE_MASK) {
268 kmem_cache_free(vm_area_cachep, vma);
269 return (int)vdso_base;
270 }
271
272 current->thread.vdso_base = vdso_base;
273
274 vma->vm_mm = mm;
275 vma->vm_start = current->thread.vdso_base;
276 vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
277
278 /*
279 * our vma flags don't have VM_WRITE so by default, the process isn't
280 * allowed to write those pages.
281 * gdb can break that with ptrace interface, and thus trigger COW on
282 * those pages but it's then your responsibility to never do that on
283 * the "data" page of the vDSO or you'll stop getting kernel updates
284 * and your nice userland gettimeofday will be totally dead.
285 * It's fine to use that for setting breakpoints in the vDSO code
286 * pages though
287 */
288 vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE |
289 VM_MAYEXEC | VM_RESERVED;
290 vma->vm_flags |= mm->def_flags;
291 vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
292 vma->vm_ops = &vdso_vmops;
293
294 down_write(&mm->mmap_sem);
295 if (insert_vm_struct(mm, vma)) {
296 up_write(&mm->mmap_sem);
297 kmem_cache_free(vm_area_cachep, vma);
298 return -ENOMEM;
299 }
300 mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
301 up_write(&mm->mmap_sem);
302
303 return 0;
304}
305
306static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
307 unsigned long *size)
308{
309 Elf32_Shdr *sechdrs;
310 unsigned int i;
311 char *secnames;
312
313 /* Grab section headers and strings so we can tell who is who */
314 sechdrs = (void *)ehdr + ehdr->e_shoff;
315 secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
316
317 /* Find the section they want */
318 for (i = 1; i < ehdr->e_shnum; i++) {
319 if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
320 if (size)
321 *size = sechdrs[i].sh_size;
322 return (void *)ehdr + sechdrs[i].sh_offset;
323 }
324 }
325 *size = 0;
326 return NULL;
327}
328
329static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib,
330 const char *symname)
331{
332 unsigned int i;
333 char name[MAX_SYMNAME], *c;
334
335 for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) {
336 if (lib->dynsym[i].st_name == 0)
337 continue;
338 strlcpy(name, lib->dynstr + lib->dynsym[i].st_name,
339 MAX_SYMNAME);
340 c = strchr(name, '@');
341 if (c)
342 *c = 0;
343 if (strcmp(symname, name) == 0)
344 return &lib->dynsym[i];
345 }
346 return NULL;
347}
348
349/* Note that we assume the section is .text and the symbol is relative to
350 * the library base
351 */
352static unsigned long __init find_function32(struct lib32_elfinfo *lib,
353 const char *symname)
354{
355 Elf32_Sym *sym = find_symbol32(lib, symname);
356
357 if (sym == NULL) {
358 printk(KERN_WARNING "vDSO32: function %s not found !\n",
359 symname);
360 return 0;
361 }
362 return sym->st_value - VDSO32_LBASE;
363}
364
365static int vdso_do_func_patch32(struct lib32_elfinfo *v32,
366 struct lib64_elfinfo *v64,
367 const char *orig, const char *fix)
368{
369 Elf32_Sym *sym32_gen, *sym32_fix;
370
371 sym32_gen = find_symbol32(v32, orig);
372 if (sym32_gen == NULL) {
373 printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig);
374 return -1;
375 }
376 if (fix == NULL) {
377 sym32_gen->st_name = 0;
378 return 0;
379 }
380 sym32_fix = find_symbol32(v32, fix);
381 if (sym32_fix == NULL) {
382 printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix);
383 return -1;
384 }
385 sym32_gen->st_value = sym32_fix->st_value;
386 sym32_gen->st_size = sym32_fix->st_size;
387 sym32_gen->st_info = sym32_fix->st_info;
388 sym32_gen->st_other = sym32_fix->st_other;
389 sym32_gen->st_shndx = sym32_fix->st_shndx;
390
391 return 0;
392}
393
394
395#ifdef CONFIG_PPC64
396
397static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname,
398 unsigned long *size)
399{
400 Elf64_Shdr *sechdrs;
401 unsigned int i;
402 char *secnames;
403
404 /* Grab section headers and strings so we can tell who is who */
405 sechdrs = (void *)ehdr + ehdr->e_shoff;
406 secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
407
408 /* Find the section they want */
409 for (i = 1; i < ehdr->e_shnum; i++) {
410 if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
411 if (size)
412 *size = sechdrs[i].sh_size;
413 return (void *)ehdr + sechdrs[i].sh_offset;
414 }
415 }
416 if (size)
417 *size = 0;
418 return NULL;
419}
420
421static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib,
422 const char *symname)
423{
424 unsigned int i;
425 char name[MAX_SYMNAME], *c;
426
427 for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) {
428 if (lib->dynsym[i].st_name == 0)
429 continue;
430 strlcpy(name, lib->dynstr + lib->dynsym[i].st_name,
431 MAX_SYMNAME);
432 c = strchr(name, '@');
433 if (c)
434 *c = 0;
435 if (strcmp(symname, name) == 0)
436 return &lib->dynsym[i];
437 }
438 return NULL;
439}
440
441/* Note that we assume the section is .text and the symbol is relative to
442 * the library base
443 */
444static unsigned long __init find_function64(struct lib64_elfinfo *lib,
445 const char *symname)
446{
447 Elf64_Sym *sym = find_symbol64(lib, symname);
448
449 if (sym == NULL) {
450 printk(KERN_WARNING "vDSO64: function %s not found !\n",
451 symname);
452 return 0;
453 }
454#ifdef VDS64_HAS_DESCRIPTORS
455 return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) -
456 VDSO64_LBASE;
457#else
458 return sym->st_value - VDSO64_LBASE;
459#endif
460}
461
462static int vdso_do_func_patch64(struct lib32_elfinfo *v32,
463 struct lib64_elfinfo *v64,
464 const char *orig, const char *fix)
465{
466 Elf64_Sym *sym64_gen, *sym64_fix;
467
468 sym64_gen = find_symbol64(v64, orig);
469 if (sym64_gen == NULL) {
470 printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig);
471 return -1;
472 }
473 if (fix == NULL) {
474 sym64_gen->st_name = 0;
475 return 0;
476 }
477 sym64_fix = find_symbol64(v64, fix);
478 if (sym64_fix == NULL) {
479 printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix);
480 return -1;
481 }
482 sym64_gen->st_value = sym64_fix->st_value;
483 sym64_gen->st_size = sym64_fix->st_size;
484 sym64_gen->st_info = sym64_fix->st_info;
485 sym64_gen->st_other = sym64_fix->st_other;
486 sym64_gen->st_shndx = sym64_fix->st_shndx;
487
488 return 0;
489}
490
491#endif /* CONFIG_PPC64 */
492
493
494static __init int vdso_do_find_sections(struct lib32_elfinfo *v32,
495 struct lib64_elfinfo *v64)
496{
497 void *sect;
498
499 /*
500 * Locate symbol tables & text section
501 */
502
503 v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize);
504 v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL);
505 if (v32->dynsym == NULL || v32->dynstr == NULL) {
506 printk(KERN_ERR "vDSO32: required symbol section not found\n");
507 return -1;
508 }
509 sect = find_section32(v32->hdr, ".text", NULL);
510 if (sect == NULL) {
511 printk(KERN_ERR "vDSO32: the .text section was not found\n");
512 return -1;
513 }
514 v32->text = sect - vdso32_kbase;
515
516#ifdef CONFIG_PPC64
517 v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize);
518 v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL);
519 if (v64->dynsym == NULL || v64->dynstr == NULL) {
520 printk(KERN_ERR "vDSO64: required symbol section not found\n");
521 return -1;
522 }
523 sect = find_section64(v64->hdr, ".text", NULL);
524 if (sect == NULL) {
525 printk(KERN_ERR "vDSO64: the .text section was not found\n");
526 return -1;
527 }
528 v64->text = sect - vdso64_kbase;
529#endif /* CONFIG_PPC64 */
530
531 return 0;
532}
533
534static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32,
535 struct lib64_elfinfo *v64)
536{
537 /*
538 * Find signal trampolines
539 */
540
541#ifdef CONFIG_PPC64
542 vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64");
543#endif
544 vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32");
545 vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32");
546}
547
548static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32,
549 struct lib64_elfinfo *v64)
550{
551 Elf32_Sym *sym32;
552#ifdef CONFIG_PPC64
553 Elf64_Sym *sym64;
554
555 sym64 = find_symbol64(v64, "__kernel_datapage_offset");
556 if (sym64 == NULL) {
557 printk(KERN_ERR "vDSO64: Can't find symbol "
558 "__kernel_datapage_offset !\n");
559 return -1;
560 }
561 *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) =
562 (vdso64_pages << PAGE_SHIFT) -
563 (sym64->st_value - VDSO64_LBASE);
564#endif /* CONFIG_PPC64 */
565
566 sym32 = find_symbol32(v32, "__kernel_datapage_offset");
567 if (sym32 == NULL) {
568 printk(KERN_ERR "vDSO32: Can't find symbol "
569 "__kernel_datapage_offset !\n");
570 return -1;
571 }
572 *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) =
573 (vdso32_pages << PAGE_SHIFT) -
574 (sym32->st_value - VDSO32_LBASE);
575
576 return 0;
577}
578
579static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32,
580 struct lib64_elfinfo *v64)
581{
582 int i;
583
584 for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) {
585 struct vdso_patch_def *patch = &vdso_patches[i];
586 int match = (cur_cpu_spec->cpu_features & patch->ftr_mask)
587 == patch->ftr_value;
588 if (!match)
589 continue;
590
591 DBG("replacing %s with %s...\n", patch->gen_name,
592 patch->fix_name ? "NONE" : patch->fix_name);
593
594 /*
595 * Patch the 32 bits and 64 bits symbols. Note that we do not
596 * patch the "." symbol on 64 bits.
597 * It would be easy to do, but doesn't seem to be necessary,
598 * patching the OPD symbol is enough.
599 */
600 vdso_do_func_patch32(v32, v64, patch->gen_name,
601 patch->fix_name);
602#ifdef CONFIG_PPC64
603 vdso_do_func_patch64(v32, v64, patch->gen_name,
604 patch->fix_name);
605#endif /* CONFIG_PPC64 */
606 }
607
608 return 0;
609}
610
611
612static __init int vdso_setup(void)
613{
614 struct lib32_elfinfo v32;
615 struct lib64_elfinfo v64;
616
617 v32.hdr = vdso32_kbase;
618#ifdef CONFIG_PPC64
619 v64.hdr = vdso64_kbase;
620#endif
621 if (vdso_do_find_sections(&v32, &v64))
622 return -1;
623
624 if (vdso_fixup_datapage(&v32, &v64))
625 return -1;
626
627 if (vdso_fixup_alt_funcs(&v32, &v64))
628 return -1;
629
630 vdso_setup_trampolines(&v32, &v64);
631
632 return 0;
633}
634
635/*
636 * Called from setup_arch to initialize the bitmap of available
637 * syscalls in the systemcfg page
638 */
639static void __init vdso_setup_syscall_map(void)
640{
641 unsigned int i;
642 extern unsigned long *sys_call_table;
643 extern unsigned long sys_ni_syscall;
644
645
646 for (i = 0; i < __NR_syscalls; i++) {
647#ifdef CONFIG_PPC64
648 if (sys_call_table[i*2] != sys_ni_syscall)
649 vdso_data->syscall_map_64[i >> 5] |=
650 0x80000000UL >> (i & 0x1f);
651 if (sys_call_table[i*2+1] != sys_ni_syscall)
652 vdso_data->syscall_map_32[i >> 5] |=
653 0x80000000UL >> (i & 0x1f);
654#else /* CONFIG_PPC64 */
655 if (sys_call_table[i] != sys_ni_syscall)
656 vdso_data->syscall_map_32[i >> 5] |=
657 0x80000000UL >> (i & 0x1f);
658#endif /* CONFIG_PPC64 */
659 }
660}
661
662
663void __init vdso_init(void)
664{
665 int i;
666
667#ifdef CONFIG_PPC64
668 /*
669 * Fill up the "systemcfg" stuff for backward compatiblity
670 */
671 strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
672 vdso_data->version.major = SYSTEMCFG_MAJOR;
673 vdso_data->version.minor = SYSTEMCFG_MINOR;
674 vdso_data->processor = mfspr(SPRN_PVR);
675 vdso_data->platform = _machine;
676 vdso_data->physicalMemorySize = lmb_phys_mem_size();
677 vdso_data->dcache_size = ppc64_caches.dsize;
678 vdso_data->dcache_line_size = ppc64_caches.dline_size;
679 vdso_data->icache_size = ppc64_caches.isize;
680 vdso_data->icache_line_size = ppc64_caches.iline_size;
681
682 /*
683 * Calculate the size of the 64 bits vDSO
684 */
685 vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT;
686 DBG("vdso64_kbase: %p, 0x%x pages\n", vdso64_kbase, vdso64_pages);
687#endif /* CONFIG_PPC64 */
688
689
690 /*
691 * Calculate the size of the 32 bits vDSO
692 */
693 vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT;
694 DBG("vdso32_kbase: %p, 0x%x pages\n", vdso32_kbase, vdso32_pages);
695
696
697 /*
698 * Setup the syscall map in the vDOS
699 */
700 vdso_setup_syscall_map();
701 /*
702 * Initialize the vDSO images in memory, that is do necessary
703 * fixups of vDSO symbols, locate trampolines, etc...
704 */
705 if (vdso_setup()) {
706 printk(KERN_ERR "vDSO setup failure, not enabled !\n");
707 vdso32_pages = 0;
708#ifdef CONFIG_PPC64
709 vdso64_pages = 0;
710#endif
711 return;
712 }
713
714 /* Make sure pages are in the correct state */
715 for (i = 0; i < vdso32_pages; i++) {
716 struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
717 ClearPageReserved(pg);
718 get_page(pg);
719
720 }
721#ifdef CONFIG_PPC64
722 for (i = 0; i < vdso64_pages; i++) {
723 struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
724 ClearPageReserved(pg);
725 get_page(pg);
726 }
727#endif /* CONFIG_PPC64 */
728
729 get_page(virt_to_page(vdso_data));
730}
731
732int in_gate_area_no_task(unsigned long addr)
733{
734 return 0;
735}
736
737int in_gate_area(struct task_struct *task, unsigned long addr)
738{
739 return 0;
740}
741
742struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
743{
744 return NULL;
745}
746
diff --git a/arch/ppc64/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 0b1b0df973eb..8a3bed5f143a 100644
--- a/arch/ppc64/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -5,6 +5,10 @@ obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
5 5
6# Build rules 6# Build rules
7 7
8ifeq ($(CONFIG_PPC32),y)
9CROSS32CC := $(CC)
10endif
11
8targets := $(obj-vdso32) vdso32.so 12targets := $(obj-vdso32) vdso32.so
9obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) 13obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
10 14
@@ -15,7 +19,7 @@ EXTRA_AFLAGS := -D__VDSO32__ -s
15 19
16obj-y += vdso32_wrapper.o 20obj-y += vdso32_wrapper.o
17extra-y += vdso32.lds 21extra-y += vdso32.lds
18CPPFLAGS_vdso32.lds += -P -C -U$(ARCH) 22CPPFLAGS_vdso32.lds += -P -C -Upowerpc
19 23
20# Force dependency (incbin is bad) 24# Force dependency (incbin is bad)
21$(obj)/vdso32_wrapper.o : $(obj)/vdso32.so 25$(obj)/vdso32_wrapper.o : $(obj)/vdso32.so
diff --git a/arch/ppc64/kernel/vdso32/cacheflush.S b/arch/powerpc/kernel/vdso32/cacheflush.S
index c8db993574ee..c8db993574ee 100644
--- a/arch/ppc64/kernel/vdso32/cacheflush.S
+++ b/arch/powerpc/kernel/vdso32/cacheflush.S
diff --git a/arch/ppc64/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S
index 4f4eb0be3992..a08c26e87835 100644
--- a/arch/ppc64/kernel/vdso32/datapage.S
+++ b/arch/powerpc/kernel/vdso32/datapage.S
@@ -66,3 +66,19 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
66 blr 66 blr
67 .cfi_endproc 67 .cfi_endproc
68V_FUNCTION_END(__kernel_get_syscall_map) 68V_FUNCTION_END(__kernel_get_syscall_map)
69
70/*
71 * void unsigned long long __kernel_get_tbfreq(void);
72 *
73 * returns the timebase frequency in HZ
74 */
75V_FUNCTION_BEGIN(__kernel_get_tbfreq)
76 .cfi_startproc
77 mflr r12
78 .cfi_register lr,r12
79 bl __get_datapage@local
80 lwz r3,CFG_TB_TICKS_PER_SEC(r3)
81 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
82 mtlr r12
83 .cfi_endproc
84V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
new file mode 100644
index 000000000000..aeb5fc9b87b3
--- /dev/null
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -0,0 +1,315 @@
1/*
2 * Userland implementation of gettimeofday() for 32 bits processes in a
3 * ppc64 kernel for use in the vDSO
4 *
5 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org,
6 * IBM Corp.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <linux/config.h>
14#include <asm/processor.h>
15#include <asm/ppc_asm.h>
16#include <asm/vdso.h>
17#include <asm/asm-offsets.h>
18#include <asm/unistd.h>
19
20 .text
21/*
22 * Exact prototype of gettimeofday
23 *
24 * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
25 *
26 */
27V_FUNCTION_BEGIN(__kernel_gettimeofday)
28 .cfi_startproc
29 mflr r12
30 .cfi_register lr,r12
31
32 mr r10,r3 /* r10 saves tv */
33 mr r11,r4 /* r11 saves tz */
34 bl __get_datapage@local /* get data page */
35 mr r9, r3 /* datapage ptr in r9 */
36 bl __do_get_xsec@local /* get xsec from tb & kernel */
37 bne- 2f /* out of line -> do syscall */
38
39 /* seconds are xsec >> 20 */
40 rlwinm r5,r4,12,20,31
41 rlwimi r5,r3,12,0,19
42 stw r5,TVAL32_TV_SEC(r10)
43
44 /* get remaining xsec and convert to usec. we scale
45 * up remaining xsec by 12 bits and get the top 32 bits
46 * of the multiplication
47 */
48 rlwinm r5,r4,12,0,19
49 lis r6,1000000@h
50 ori r6,r6,1000000@l
51 mulhwu r5,r5,r6
52 stw r5,TVAL32_TV_USEC(r10)
53
54 cmpli cr0,r11,0 /* check if tz is NULL */
55 beq 1f
56 lwz r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
57 lwz r5,CFG_TZ_DSTTIME(r9)
58 stw r4,TZONE_TZ_MINWEST(r11)
59 stw r5,TZONE_TZ_DSTTIME(r11)
60
611: mtlr r12
62 li r3,0
63 blr
64
652:
66 mtlr r12
67 mr r3,r10
68 mr r4,r11
69 li r0,__NR_gettimeofday
70 sc
71 blr
72 .cfi_endproc
73V_FUNCTION_END(__kernel_gettimeofday)
74
75/*
76 * Exact prototype of clock_gettime()
77 *
78 * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp);
79 *
80 */
81V_FUNCTION_BEGIN(__kernel_clock_gettime)
82 .cfi_startproc
83 /* Check for supported clock IDs */
84 cmpli cr0,r3,CLOCK_REALTIME
85 cmpli cr1,r3,CLOCK_MONOTONIC
86 cror cr0,cr0,cr1
87 bne cr0,99f
88
89 mflr r12 /* r12 saves lr */
90 .cfi_register lr,r12
91 mr r10,r3 /* r10 saves id */
92 mr r11,r4 /* r11 saves tp */
93 bl __get_datapage@local /* get data page */
94 mr r9, r3 /* datapage ptr in r9 */
95 beq cr1,50f /* if monotonic -> jump there */
96
97 /*
98 * CLOCK_REALTIME
99 */
100
101 bl __do_get_xsec@local /* get xsec from tb & kernel */
102 bne- 98f /* out of line -> do syscall */
103
104 /* seconds are xsec >> 20 */
105 rlwinm r5,r4,12,20,31
106 rlwimi r5,r3,12,0,19
107 stw r5,TSPC32_TV_SEC(r11)
108
109 /* get remaining xsec and convert to nsec. we scale
110 * up remaining xsec by 12 bits and get the top 32 bits
111 * of the multiplication, then we multiply by 1000
112 */
113 rlwinm r5,r4,12,0,19
114 lis r6,1000000@h
115 ori r6,r6,1000000@l
116 mulhwu r5,r5,r6
117 mulli r5,r5,1000
118 stw r5,TSPC32_TV_NSEC(r11)
119 mtlr r12
120 li r3,0
121 blr
122
123 /*
124 * CLOCK_MONOTONIC
125 */
126
12750: bl __do_get_xsec@local /* get xsec from tb & kernel */
128 bne- 98f /* out of line -> do syscall */
129
130 /* seconds are xsec >> 20 */
131 rlwinm r6,r4,12,20,31
132 rlwimi r6,r3,12,0,19
133
134 /* get remaining xsec and convert to nsec. we scale
135 * up remaining xsec by 12 bits and get the top 32 bits
136 * of the multiplication, then we multiply by 1000
137 */
138 rlwinm r7,r4,12,0,19
139 lis r5,1000000@h
140 ori r5,r5,1000000@l
141 mulhwu r7,r7,r5
142 mulli r7,r7,1000
143
144 /* now we must fixup using wall to monotonic. We need to snapshot
145 * that value and do the counter trick again. Fortunately, we still
146 * have the counter value in r8 that was returned by __do_get_xsec.
147 * At this point, r6,r7 contain our sec/nsec values, r3,r4 and r5
148 * can be used
149 */
150
151 lwz r3,WTOM_CLOCK_SEC(r9)
152 lwz r4,WTOM_CLOCK_NSEC(r9)
153
154 /* We now have our result in r3,r4. We create a fake dependency
155 * on that result and re-check the counter
156 */
157 or r5,r4,r3
158 xor r0,r5,r5
159 add r9,r9,r0
160#ifdef CONFIG_PPC64
161 lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
162#else
163 lwz r0,(CFG_TB_UPDATE_COUNT)(r9)
164#endif
165 cmpl cr0,r8,r0 /* check if updated */
166 bne- 50b
167
168 /* Calculate and store result. Note that this mimmics the C code,
169 * which may cause funny results if nsec goes negative... is that
170 * possible at all ?
171 */
172 add r3,r3,r6
173 add r4,r4,r7
174 lis r5,NSEC_PER_SEC@h
175 ori r5,r5,NSEC_PER_SEC@l
176 cmpli cr0,r4,r5
177 blt 1f
178 subf r4,r5,r4
179 addi r3,r3,1
1801: stw r3,TSPC32_TV_SEC(r11)
181 stw r4,TSPC32_TV_NSEC(r11)
182
183 mtlr r12
184 li r3,0
185 blr
186
187 /*
188 * syscall fallback
189 */
19098:
191 mtlr r12
192 mr r3,r10
193 mr r4,r11
19499:
195 li r0,__NR_clock_gettime
196 sc
197 blr
198 .cfi_endproc
199V_FUNCTION_END(__kernel_clock_gettime)
200
201
202/*
203 * Exact prototype of clock_getres()
204 *
205 * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res);
206 *
207 */
208V_FUNCTION_BEGIN(__kernel_clock_getres)
209 .cfi_startproc
210 /* Check for supported clock IDs */
211 cmpwi cr0,r3,CLOCK_REALTIME
212 cmpwi cr1,r3,CLOCK_MONOTONIC
213 cror cr0,cr0,cr1
214 bne cr0,99f
215
216 li r3,0
217 cmpli cr0,r4,0
218 beqlr
219 lis r5,CLOCK_REALTIME_RES@h
220 ori r5,r5,CLOCK_REALTIME_RES@l
221 stw r3,TSPC32_TV_SEC(r4)
222 stw r5,TSPC32_TV_NSEC(r4)
223 blr
224
225 /*
226 * syscall fallback
227 */
22899:
229 li r0,__NR_clock_getres
230 sc
231 blr
232 .cfi_endproc
233V_FUNCTION_END(__kernel_clock_getres)
234
235
236/*
237 * This is the core of gettimeofday() & friends, it returns the xsec
238 * value in r3 & r4 and expects the datapage ptr (non clobbered)
239 * in r9. clobbers r0,r4,r5,r6,r7,r8.
240 * When returning, r8 contains the counter value that can be reused
241 * by the monotonic clock implementation
242 */
243__do_get_xsec:
244 .cfi_startproc
245 /* Check for update count & load values. We use the low
246 * order 32 bits of the update count
247 */
248#ifdef CONFIG_PPC64
2491: lwz r8,(CFG_TB_UPDATE_COUNT+4)(r9)
250#else
2511: lwz r8,(CFG_TB_UPDATE_COUNT)(r9)
252#endif
253 andi. r0,r8,1 /* pending update ? loop */
254 bne- 1b
255 xor r0,r8,r8 /* create dependency */
256 add r9,r9,r0
257
258 /* Load orig stamp (offset to TB) */
259 lwz r5,CFG_TB_ORIG_STAMP(r9)
260 lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
261
262 /* Get a stable TB value */
2632: mftbu r3
264 mftbl r4
265 mftbu r0
266 cmpl cr0,r3,r0
267 bne- 2b
268
269 /* Substract tb orig stamp. If the high part is non-zero, we jump to
270 * the slow path which call the syscall.
271 * If it's ok, then we have our 32 bits tb_ticks value in r7
272 */
273 subfc r7,r6,r4
274 subfe. r0,r5,r3
275 bne- 3f
276
277 /* Load scale factor & do multiplication */
278 lwz r5,CFG_TB_TO_XS(r9) /* load values */
279 lwz r6,(CFG_TB_TO_XS+4)(r9)
280 mulhwu r4,r7,r5
281 mulhwu r6,r7,r6
282 mullw r0,r7,r5
283 addc r6,r6,r0
284
285 /* At this point, we have the scaled xsec value in r4 + XER:CA
286 * we load & add the stamp since epoch
287 */
288 lwz r5,CFG_STAMP_XSEC(r9)
289 lwz r6,(CFG_STAMP_XSEC+4)(r9)
290 adde r4,r4,r6
291 addze r3,r5
292
293 /* We now have our result in r3,r4. We create a fake dependency
294 * on that result and re-check the counter
295 */
296 or r6,r4,r3
297 xor r0,r6,r6
298 add r9,r9,r0
299#ifdef CONFIG_PPC64
300 lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
301#else
302 lwz r0,(CFG_TB_UPDATE_COUNT)(r9)
303#endif
304 cmpl cr0,r8,r0 /* check if updated */
305 bne- 1b
306
307 /* Warning ! The caller expects CR:EQ to be set to indicate a
308 * successful calculation (so it won't fallback to the syscall
309 * method). We have overriden that CR bit in the counter check,
310 * but fortunately, the loop exit condition _is_ CR:EQ set, so
311 * we can exit safely here. If you change this code, be careful
312 * of that side effect.
313 */
3143: blr
315 .cfi_endproc
diff --git a/arch/ppc64/kernel/vdso32/note.S b/arch/powerpc/kernel/vdso32/note.S
index d4b5be4f3d5f..d4b5be4f3d5f 100644
--- a/arch/ppc64/kernel/vdso32/note.S
+++ b/arch/powerpc/kernel/vdso32/note.S
diff --git a/arch/ppc64/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S
index e04642781917..e04642781917 100644
--- a/arch/ppc64/kernel/vdso32/sigtramp.S
+++ b/arch/powerpc/kernel/vdso32/sigtramp.S
diff --git a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index 6f87a916a394..f4bad720cb0a 100644
--- a/arch/ppc64/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -102,9 +102,12 @@ VERSION
102{ 102{
103 VDSO_VERSION_STRING { 103 VDSO_VERSION_STRING {
104 global: 104 global:
105 __kernel_datapage_offset; /* Has to be there for the kernel to find it */ 105 __kernel_datapage_offset; /* Has to be there for the kernel to find */
106 __kernel_get_syscall_map; 106 __kernel_get_syscall_map;
107 __kernel_gettimeofday; 107 __kernel_gettimeofday;
108 __kernel_clock_gettime;
109 __kernel_clock_getres;
110 __kernel_get_tbfreq;
108 __kernel_sync_dicache; 111 __kernel_sync_dicache;
109 __kernel_sync_dicache_p5; 112 __kernel_sync_dicache_p5;
110 __kernel_sigtramp32; 113 __kernel_sigtramp32;
diff --git a/arch/ppc64/kernel/vdso32/vdso32_wrapper.S b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S
index 76ca28e09d29..556f0caa5d84 100644
--- a/arch/ppc64/kernel/vdso32/vdso32_wrapper.S
+++ b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S
@@ -6,7 +6,7 @@
6 .globl vdso32_start, vdso32_end 6 .globl vdso32_start, vdso32_end
7 .balign PAGE_SIZE 7 .balign PAGE_SIZE
8vdso32_start: 8vdso32_start:
9 .incbin "arch/ppc64/kernel/vdso32/vdso32.so" 9 .incbin "arch/powerpc/kernel/vdso32/vdso32.so"
10 .balign PAGE_SIZE 10 .balign PAGE_SIZE
11vdso32_end: 11vdso32_end:
12 12
diff --git a/arch/ppc64/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index ab39988452cc..ab39988452cc 100644
--- a/arch/ppc64/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
diff --git a/arch/ppc64/kernel/vdso64/cacheflush.S b/arch/powerpc/kernel/vdso64/cacheflush.S
index d4a0ad28d534..d4a0ad28d534 100644
--- a/arch/ppc64/kernel/vdso64/cacheflush.S
+++ b/arch/powerpc/kernel/vdso64/cacheflush.S
diff --git a/arch/ppc64/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S
index ed6e599ae824..e67eda0f8cda 100644
--- a/arch/ppc64/kernel/vdso64/datapage.S
+++ b/arch/powerpc/kernel/vdso64/datapage.S
@@ -66,3 +66,19 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
66 blr 66 blr
67 .cfi_endproc 67 .cfi_endproc
68V_FUNCTION_END(__kernel_get_syscall_map) 68V_FUNCTION_END(__kernel_get_syscall_map)
69
70
71/*
72 * void unsigned long __kernel_get_tbfreq(void);
73 *
74 * returns the timebase frequency in HZ
75 */
76V_FUNCTION_BEGIN(__kernel_get_tbfreq)
77 .cfi_startproc
78 mflr r12
79 .cfi_register lr,r12
80 bl V_LOCAL_FUNC(__get_datapage)
81 ld r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12
83 .cfi_endproc
84V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
new file mode 100644
index 000000000000..d371c02a8c0e
--- /dev/null
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -0,0 +1,242 @@
1/*
2 * Userland implementation of gettimeofday() for 64 bits processes in a
3 * ppc64 kernel for use in the vDSO
4 *
5 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
6 * IBM Corp.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <linux/config.h>
14#include <asm/processor.h>
15#include <asm/ppc_asm.h>
16#include <asm/vdso.h>
17#include <asm/asm-offsets.h>
18#include <asm/unistd.h>
19
20 .text
21/*
22 * Exact prototype of gettimeofday
23 *
24 * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
25 *
26 */
27V_FUNCTION_BEGIN(__kernel_gettimeofday)
28 .cfi_startproc
29 mflr r12
30 .cfi_register lr,r12
31
32 mr r11,r3 /* r11 holds tv */
33 mr r10,r4 /* r10 holds tz */
34 bl V_LOCAL_FUNC(__get_datapage) /* get data page */
35 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
36 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
37 ori r7,r7,16960
38 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
39 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
40 std r5,TVAL64_TV_SEC(r11) /* store sec in tv */
41 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
42 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
43 * XSEC_PER_SEC
44 */
45 rldicl r0,r0,44,20
46 cmpldi cr0,r10,0 /* check if tz is NULL */
47 std r0,TVAL64_TV_USEC(r11) /* store usec in tv */
48 beq 1f
49 lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
50 lwz r5,CFG_TZ_DSTTIME(r3)
51 stw r4,TZONE_TZ_MINWEST(r10)
52 stw r5,TZONE_TZ_DSTTIME(r10)
531: mtlr r12
54 li r3,0 /* always success */
55 blr
56 .cfi_endproc
57V_FUNCTION_END(__kernel_gettimeofday)
58
59
60/*
61 * Exact prototype of clock_gettime()
62 *
63 * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp);
64 *
65 */
66V_FUNCTION_BEGIN(__kernel_clock_gettime)
67 .cfi_startproc
68 /* Check for supported clock IDs */
69 cmpwi cr0,r3,CLOCK_REALTIME
70 cmpwi cr1,r3,CLOCK_MONOTONIC
71 cror cr0,cr0,cr1
72 bne cr0,99f
73
74 mflr r12 /* r12 saves lr */
75 .cfi_register lr,r12
76 mr r10,r3 /* r10 saves id */
77 mr r11,r4 /* r11 saves tp */
78 bl V_LOCAL_FUNC(__get_datapage) /* get data page */
79 beq cr1,50f /* if monotonic -> jump there */
80
81 /*
82 * CLOCK_REALTIME
83 */
84
85 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
86
87 lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */
88 ori r7,r7,0xca00
89 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
90 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
91 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
92 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
93 mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) /
94 * XSEC_PER_SEC
95 */
96 rldicl r0,r0,44,20
97 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
98
99 mtlr r12
100 li r3,0
101 blr
102
103 /*
104 * CLOCK_MONOTONIC
105 */
106
10750: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
108
109 lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */
110 ori r7,r7,0xca00
111 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
112 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
113 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
114 mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) /
115 * XSEC_PER_SEC
116 */
117 rldicl r6,r0,44,20
118
119 /* now we must fixup using wall to monotonic. We need to snapshot
120 * that value and do the counter trick again. Fortunately, we still
121 * have the counter value in r8 that was returned by __do_get_xsec.
122 * At this point, r5,r6 contain our sec/nsec values.
123 * can be used
124 */
125
126 lwz r4,WTOM_CLOCK_SEC(r9)
127 lwz r7,WTOM_CLOCK_NSEC(r9)
128
129 /* We now have our result in r4,r7. We create a fake dependency
130 * on that result and re-check the counter
131 */
132 or r9,r4,r7
133 xor r0,r9,r9
134 add r3,r3,r0
135 ld r0,CFG_TB_UPDATE_COUNT(r3)
136 cmpld cr0,r0,r8 /* check if updated */
137 bne- 50b
138
139 /* Calculate and store result. Note that this mimmics the C code,
140 * which may cause funny results if nsec goes negative... is that
141 * possible at all ?
142 */
143 add r4,r4,r5
144 add r7,r7,r6
145 lis r9,NSEC_PER_SEC@h
146 ori r9,r9,NSEC_PER_SEC@l
147 cmpli cr0,r7,r9
148 blt 1f
149 subf r7,r9,r7
150 addi r4,r4,1
1511: std r4,TSPC64_TV_SEC(r11)
152 std r7,TSPC64_TV_NSEC(r11)
153
154 mtlr r12
155 li r3,0
156 blr
157
158 /*
159 * syscall fallback
160 */
16198:
162 mtlr r12
163 mr r3,r10
164 mr r4,r11
16599:
166 li r0,__NR_clock_gettime
167 sc
168 blr
169 .cfi_endproc
170V_FUNCTION_END(__kernel_clock_gettime)
171
172
173/*
174 * Exact prototype of clock_getres()
175 *
176 * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res);
177 *
178 */
179V_FUNCTION_BEGIN(__kernel_clock_getres)
180 .cfi_startproc
181 /* Check for supported clock IDs */
182 cmpwi cr0,r3,CLOCK_REALTIME
183 cmpwi cr1,r3,CLOCK_MONOTONIC
184 cror cr0,cr0,cr1
185 bne cr0,99f
186
187 li r3,0
188 cmpli cr0,r4,0
189 beqlr
190 lis r5,CLOCK_REALTIME_RES@h
191 ori r5,r5,CLOCK_REALTIME_RES@l
192 std r3,TSPC64_TV_SEC(r4)
193 std r5,TSPC64_TV_NSEC(r4)
194 blr
195
196 /*
197 * syscall fallback
198 */
19999:
200 li r0,__NR_clock_getres
201 sc
202 blr
203 .cfi_endproc
204V_FUNCTION_END(__kernel_clock_getres)
205
206
207/*
208 * This is the core of gettimeofday(), it returns the xsec
209 * value in r4 and expects the datapage ptr (non clobbered)
210 * in r3. clobbers r0,r4,r5,r6,r7,r8
211 * When returning, r8 contains the counter value that can be reused
212 */
213V_FUNCTION_BEGIN(__do_get_xsec)
214 .cfi_startproc
215 /* check for update count & load values */
2161: ld r8,CFG_TB_UPDATE_COUNT(r3)
217 andi. r0,r4,1 /* pending update ? loop */
218 bne- 1b
219 xor r0,r4,r4 /* create dependency */
220 add r3,r3,r0
221
222 /* Get TB & offset it */
223 mftb r7
224 ld r9,CFG_TB_ORIG_STAMP(r3)
225 subf r7,r9,r7
226
227 /* Scale result */
228 ld r5,CFG_TB_TO_XS(r3)
229 mulhdu r7,r7,r5
230
231 /* Add stamp since epoch */
232 ld r6,CFG_STAMP_XSEC(r3)
233 add r4,r6,r7
234
235 xor r0,r4,r4
236 add r3,r3,r0
237 ld r0,CFG_TB_UPDATE_COUNT(r3)
238 cmpld cr0,r0,r8 /* check if updated */
239 bne- 1b
240 blr
241 .cfi_endproc
242V_FUNCTION_END(__do_get_xsec)
diff --git a/arch/ppc64/kernel/vdso64/note.S b/arch/powerpc/kernel/vdso64/note.S
index dc2a509f7e8a..dc2a509f7e8a 100644
--- a/arch/ppc64/kernel/vdso64/note.S
+++ b/arch/powerpc/kernel/vdso64/note.S
diff --git a/arch/ppc64/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S
index 31b604ab56de..31b604ab56de 100644
--- a/arch/ppc64/kernel/vdso64/sigtramp.S
+++ b/arch/powerpc/kernel/vdso64/sigtramp.S
diff --git a/arch/ppc64/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index 9cb28181da80..4bdf224464ab 100644
--- a/arch/ppc64/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -102,9 +102,12 @@ VERSION
102{ 102{
103 VDSO_VERSION_STRING { 103 VDSO_VERSION_STRING {
104 global: 104 global:
105 __kernel_datapage_offset; /* Has to be there for the kernel to find it */ 105 __kernel_datapage_offset; /* Has to be there for the kernel to find */
106 __kernel_get_syscall_map; 106 __kernel_get_syscall_map;
107 __kernel_gettimeofday; 107 __kernel_gettimeofday;
108 __kernel_clock_gettime;
109 __kernel_clock_getres;
110 __kernel_get_tbfreq;
108 __kernel_sync_dicache; 111 __kernel_sync_dicache;
109 __kernel_sync_dicache_p5; 112 __kernel_sync_dicache_p5;
110 __kernel_sigtramp_rt64; 113 __kernel_sigtramp_rt64;
diff --git a/arch/ppc64/kernel/vdso64/vdso64_wrapper.S b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S
index 771c2741c492..0529cb9e3b97 100644
--- a/arch/ppc64/kernel/vdso64/vdso64_wrapper.S
+++ b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S
@@ -6,7 +6,7 @@
6 .globl vdso64_start, vdso64_end 6 .globl vdso64_start, vdso64_end
7 .balign PAGE_SIZE 7 .balign PAGE_SIZE
8vdso64_start: 8vdso64_start:
9 .incbin "arch/ppc64/kernel/vdso64/vdso64.so" 9 .incbin "arch/powerpc/kernel/vdso64/vdso64.so"
10 .balign PAGE_SIZE 10 .balign PAGE_SIZE
11vdso64_end: 11vdso64_end:
12 12
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 1dd3cc69a490..e2c95fcb8055 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -46,9 +46,7 @@
46#include <asm/prom.h> 46#include <asm/prom.h>
47#include <asm/lmb.h> 47#include <asm/lmb.h>
48#include <asm/sections.h> 48#include <asm/sections.h>
49#ifdef CONFIG_PPC64
50#include <asm/vdso.h> 49#include <asm/vdso.h>
51#endif
52 50
53#include "mmu_decl.h" 51#include "mmu_decl.h"
54 52
@@ -397,10 +395,8 @@ void __init mem_init(void)
397 395
398 mem_init_done = 1; 396 mem_init_done = 1;
399 397
400#ifdef CONFIG_PPC64
401 /* Initialize the vDSO */ 398 /* Initialize the vDSO */
402 vdso_init(); 399 vdso_init();
403#endif
404} 400}
405 401
406/* 402/*
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index da09ba03c424..bd2cf1336885 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -17,9 +17,8 @@
17#include <linux/nodemask.h> 17#include <linux/nodemask.h>
18#include <linux/cpu.h> 18#include <linux/cpu.h>
19#include <linux/notifier.h> 19#include <linux/notifier.h>
20#include <asm/sparsemem.h>
20#include <asm/lmb.h> 21#include <asm/lmb.h>
21#include <asm/machdep.h>
22#include <asm/abs_addr.h>
23#include <asm/system.h> 22#include <asm/system.h>
24#include <asm/smp.h> 23#include <asm/smp.h>
25 24
@@ -28,45 +27,113 @@ static int numa_enabled = 1;
28static int numa_debug; 27static int numa_debug;
29#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); } 28#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
30 29
31#ifdef DEBUG_NUMA 30int numa_cpu_lookup_table[NR_CPUS];
32#define ARRAY_INITIALISER -1
33#else
34#define ARRAY_INITIALISER 0
35#endif
36
37int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] =
38 ARRAY_INITIALISER};
39char *numa_memory_lookup_table;
40cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; 31cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
41int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
42
43struct pglist_data *node_data[MAX_NUMNODES]; 32struct pglist_data *node_data[MAX_NUMNODES];
44bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; 33
34EXPORT_SYMBOL(numa_cpu_lookup_table);
35EXPORT_SYMBOL(numa_cpumask_lookup_table);
36EXPORT_SYMBOL(node_data);
37
38static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
45static int min_common_depth; 39static int min_common_depth;
46 40
47/* 41/*
48 * We need somewhere to store start/span for each node until we have 42 * We need somewhere to store start/end/node for each region until we have
49 * allocated the real node_data structures. 43 * allocated the real node_data structures.
50 */ 44 */
45#define MAX_REGIONS (MAX_LMB_REGIONS*2)
51static struct { 46static struct {
52 unsigned long node_start_pfn; 47 unsigned long start_pfn;
53 unsigned long node_end_pfn; 48 unsigned long end_pfn;
54 unsigned long node_present_pages; 49 int nid;
55} init_node_data[MAX_NUMNODES] __initdata; 50} init_node_data[MAX_REGIONS] __initdata;
56 51
57EXPORT_SYMBOL(node_data); 52int __init early_pfn_to_nid(unsigned long pfn)
58EXPORT_SYMBOL(numa_cpu_lookup_table); 53{
59EXPORT_SYMBOL(numa_memory_lookup_table); 54 unsigned int i;
60EXPORT_SYMBOL(numa_cpumask_lookup_table); 55
61EXPORT_SYMBOL(nr_cpus_in_node); 56 for (i = 0; init_node_data[i].end_pfn; i++) {
57 unsigned long start_pfn = init_node_data[i].start_pfn;
58 unsigned long end_pfn = init_node_data[i].end_pfn;
59
60 if ((start_pfn <= pfn) && (pfn < end_pfn))
61 return init_node_data[i].nid;
62 }
63
64 return -1;
65}
66
67void __init add_region(unsigned int nid, unsigned long start_pfn,
68 unsigned long pages)
69{
70 unsigned int i;
71
72 dbg("add_region nid %d start_pfn 0x%lx pages 0x%lx\n",
73 nid, start_pfn, pages);
74
75 for (i = 0; init_node_data[i].end_pfn; i++) {
76 if (init_node_data[i].nid != nid)
77 continue;
78 if (init_node_data[i].end_pfn == start_pfn) {
79 init_node_data[i].end_pfn += pages;
80 return;
81 }
82 if (init_node_data[i].start_pfn == (start_pfn + pages)) {
83 init_node_data[i].start_pfn -= pages;
84 return;
85 }
86 }
87
88 /*
89 * Leave last entry NULL so we dont iterate off the end (we use
90 * entry.end_pfn to terminate the walk).
91 */
92 if (i >= (MAX_REGIONS - 1)) {
93 printk(KERN_ERR "WARNING: too many memory regions in "
94 "numa code, truncating\n");
95 return;
96 }
97
98 init_node_data[i].start_pfn = start_pfn;
99 init_node_data[i].end_pfn = start_pfn + pages;
100 init_node_data[i].nid = nid;
101}
102
103/* We assume init_node_data has no overlapping regions */
104void __init get_region(unsigned int nid, unsigned long *start_pfn,
105 unsigned long *end_pfn, unsigned long *pages_present)
106{
107 unsigned int i;
108
109 *start_pfn = -1UL;
110 *end_pfn = *pages_present = 0;
111
112 for (i = 0; init_node_data[i].end_pfn; i++) {
113 if (init_node_data[i].nid != nid)
114 continue;
115
116 *pages_present += init_node_data[i].end_pfn -
117 init_node_data[i].start_pfn;
118
119 if (init_node_data[i].start_pfn < *start_pfn)
120 *start_pfn = init_node_data[i].start_pfn;
121
122 if (init_node_data[i].end_pfn > *end_pfn)
123 *end_pfn = init_node_data[i].end_pfn;
124 }
125
126 /* We didnt find a matching region, return start/end as 0 */
127 if (*start_pfn == -1UL)
128 start_pfn = 0;
129}
62 130
63static inline void map_cpu_to_node(int cpu, int node) 131static inline void map_cpu_to_node(int cpu, int node)
64{ 132{
65 numa_cpu_lookup_table[cpu] = node; 133 numa_cpu_lookup_table[cpu] = node;
66 if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) { 134
135 if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node])))
67 cpu_set(cpu, numa_cpumask_lookup_table[node]); 136 cpu_set(cpu, numa_cpumask_lookup_table[node]);
68 nr_cpus_in_node[node]++;
69 }
70} 137}
71 138
72#ifdef CONFIG_HOTPLUG_CPU 139#ifdef CONFIG_HOTPLUG_CPU
@@ -78,7 +145,6 @@ static void unmap_cpu_from_node(unsigned long cpu)
78 145
79 if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) { 146 if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
80 cpu_clear(cpu, numa_cpumask_lookup_table[node]); 147 cpu_clear(cpu, numa_cpumask_lookup_table[node]);
81 nr_cpus_in_node[node]--;
82 } else { 148 } else {
83 printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n", 149 printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
84 cpu, node); 150 cpu, node);
@@ -86,7 +152,7 @@ static void unmap_cpu_from_node(unsigned long cpu)
86} 152}
87#endif /* CONFIG_HOTPLUG_CPU */ 153#endif /* CONFIG_HOTPLUG_CPU */
88 154
89static struct device_node * __devinit find_cpu_node(unsigned int cpu) 155static struct device_node *find_cpu_node(unsigned int cpu)
90{ 156{
91 unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); 157 unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
92 struct device_node *cpu_node = NULL; 158 struct device_node *cpu_node = NULL;
@@ -213,7 +279,7 @@ static int __init get_mem_size_cells(void)
213 return rc; 279 return rc;
214} 280}
215 281
216static unsigned long read_n_cells(int n, unsigned int **buf) 282static unsigned long __init read_n_cells(int n, unsigned int **buf)
217{ 283{
218 unsigned long result = 0; 284 unsigned long result = 0;
219 285
@@ -295,7 +361,8 @@ static int cpu_numa_callback(struct notifier_block *nfb,
295 * or zero. If the returned value of size is 0 the region should be 361 * or zero. If the returned value of size is 0 the region should be
296 * discarded as it lies wholy above the memory limit. 362 * discarded as it lies wholy above the memory limit.
297 */ 363 */
298static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size) 364static unsigned long __init numa_enforce_memory_limit(unsigned long start,
365 unsigned long size)
299{ 366{
300 /* 367 /*
301 * We use lmb_end_of_DRAM() in here instead of memory_limit because 368 * We use lmb_end_of_DRAM() in here instead of memory_limit because
@@ -320,8 +387,7 @@ static int __init parse_numa_properties(void)
320 struct device_node *cpu = NULL; 387 struct device_node *cpu = NULL;
321 struct device_node *memory = NULL; 388 struct device_node *memory = NULL;
322 int addr_cells, size_cells; 389 int addr_cells, size_cells;
323 int max_domain = 0; 390 int max_domain;
324 long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
325 unsigned long i; 391 unsigned long i;
326 392
327 if (numa_enabled == 0) { 393 if (numa_enabled == 0) {
@@ -329,13 +395,6 @@ static int __init parse_numa_properties(void)
329 return -1; 395 return -1;
330 } 396 }
331 397
332 numa_memory_lookup_table =
333 (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
334 memset(numa_memory_lookup_table, 0, entries * sizeof(char));
335
336 for (i = 0; i < entries ; i++)
337 numa_memory_lookup_table[i] = ARRAY_INITIALISER;
338
339 min_common_depth = find_min_common_depth(); 398 min_common_depth = find_min_common_depth();
340 399
341 dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); 400 dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth);
@@ -387,9 +446,6 @@ new_range:
387 start = read_n_cells(addr_cells, &memcell_buf); 446 start = read_n_cells(addr_cells, &memcell_buf);
388 size = read_n_cells(size_cells, &memcell_buf); 447 size = read_n_cells(size_cells, &memcell_buf);
389 448
390 start = _ALIGN_DOWN(start, MEMORY_INCREMENT);
391 size = _ALIGN_UP(size, MEMORY_INCREMENT);
392
393 numa_domain = of_node_numa_domain(memory); 449 numa_domain = of_node_numa_domain(memory);
394 450
395 if (numa_domain >= MAX_NUMNODES) { 451 if (numa_domain >= MAX_NUMNODES) {
@@ -403,44 +459,15 @@ new_range:
403 if (max_domain < numa_domain) 459 if (max_domain < numa_domain)
404 max_domain = numa_domain; 460 max_domain = numa_domain;
405 461
406 if (! (size = numa_enforce_memory_limit(start, size))) { 462 if (!(size = numa_enforce_memory_limit(start, size))) {
407 if (--ranges) 463 if (--ranges)
408 goto new_range; 464 goto new_range;
409 else 465 else
410 continue; 466 continue;
411 } 467 }
412 468
413 /* 469 add_region(numa_domain, start >> PAGE_SHIFT,
414 * Initialize new node struct, or add to an existing one. 470 size >> PAGE_SHIFT);
415 */
416 if (init_node_data[numa_domain].node_end_pfn) {
417 if ((start / PAGE_SIZE) <
418 init_node_data[numa_domain].node_start_pfn)
419 init_node_data[numa_domain].node_start_pfn =
420 start / PAGE_SIZE;
421 if (((start / PAGE_SIZE) + (size / PAGE_SIZE)) >
422 init_node_data[numa_domain].node_end_pfn)
423 init_node_data[numa_domain].node_end_pfn =
424 (start / PAGE_SIZE) +
425 (size / PAGE_SIZE);
426
427 init_node_data[numa_domain].node_present_pages +=
428 size / PAGE_SIZE;
429 } else {
430 node_set_online(numa_domain);
431
432 init_node_data[numa_domain].node_start_pfn =
433 start / PAGE_SIZE;
434 init_node_data[numa_domain].node_end_pfn =
435 init_node_data[numa_domain].node_start_pfn +
436 size / PAGE_SIZE;
437 init_node_data[numa_domain].node_present_pages =
438 size / PAGE_SIZE;
439 }
440
441 for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
442 numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
443 numa_domain;
444 471
445 if (--ranges) 472 if (--ranges)
446 goto new_range; 473 goto new_range;
@@ -456,32 +483,15 @@ static void __init setup_nonnuma(void)
456{ 483{
457 unsigned long top_of_ram = lmb_end_of_DRAM(); 484 unsigned long top_of_ram = lmb_end_of_DRAM();
458 unsigned long total_ram = lmb_phys_mem_size(); 485 unsigned long total_ram = lmb_phys_mem_size();
459 unsigned long i;
460 486
461 printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", 487 printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
462 top_of_ram, total_ram); 488 top_of_ram, total_ram);
463 printk(KERN_INFO "Memory hole size: %ldMB\n", 489 printk(KERN_INFO "Memory hole size: %ldMB\n",
464 (top_of_ram - total_ram) >> 20); 490 (top_of_ram - total_ram) >> 20);
465 491
466 if (!numa_memory_lookup_table) {
467 long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT;
468 numa_memory_lookup_table =
469 (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
470 memset(numa_memory_lookup_table, 0, entries * sizeof(char));
471 for (i = 0; i < entries ; i++)
472 numa_memory_lookup_table[i] = ARRAY_INITIALISER;
473 }
474
475 map_cpu_to_node(boot_cpuid, 0); 492 map_cpu_to_node(boot_cpuid, 0);
476 493 add_region(0, 0, lmb_end_of_DRAM() >> PAGE_SHIFT);
477 node_set_online(0); 494 node_set_online(0);
478
479 init_node_data[0].node_start_pfn = 0;
480 init_node_data[0].node_end_pfn = lmb_end_of_DRAM() / PAGE_SIZE;
481 init_node_data[0].node_present_pages = total_ram / PAGE_SIZE;
482
483 for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
484 numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
485} 495}
486 496
487static void __init dump_numa_topology(void) 497static void __init dump_numa_topology(void)
@@ -499,8 +509,9 @@ static void __init dump_numa_topology(void)
499 509
500 count = 0; 510 count = 0;
501 511
502 for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) { 512 for (i = 0; i < lmb_end_of_DRAM();
503 if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) { 513 i += (1 << SECTION_SIZE_BITS)) {
514 if (early_pfn_to_nid(i >> PAGE_SHIFT) == node) {
504 if (count == 0) 515 if (count == 0)
505 printk(" 0x%lx", i); 516 printk(" 0x%lx", i);
506 ++count; 517 ++count;
@@ -525,10 +536,12 @@ static void __init dump_numa_topology(void)
525 * 536 *
526 * Returns the physical address of the memory. 537 * Returns the physical address of the memory.
527 */ 538 */
528static unsigned long careful_allocation(int nid, unsigned long size, 539static void __init *careful_allocation(int nid, unsigned long size,
529 unsigned long align, unsigned long end) 540 unsigned long align,
541 unsigned long end_pfn)
530{ 542{
531 unsigned long ret = lmb_alloc_base(size, align, end); 543 int new_nid;
544 unsigned long ret = lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT);
532 545
533 /* retry over all memory */ 546 /* retry over all memory */
534 if (!ret) 547 if (!ret)
@@ -542,28 +555,27 @@ static unsigned long careful_allocation(int nid, unsigned long size,
542 * If the memory came from a previously allocated node, we must 555 * If the memory came from a previously allocated node, we must
543 * retry with the bootmem allocator. 556 * retry with the bootmem allocator.
544 */ 557 */
545 if (pa_to_nid(ret) < nid) { 558 new_nid = early_pfn_to_nid(ret >> PAGE_SHIFT);
546 nid = pa_to_nid(ret); 559 if (new_nid < nid) {
547 ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid), 560 ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(new_nid),
548 size, align, 0); 561 size, align, 0);
549 562
550 if (!ret) 563 if (!ret)
551 panic("numa.c: cannot allocate %lu bytes on node %d", 564 panic("numa.c: cannot allocate %lu bytes on node %d",
552 size, nid); 565 size, new_nid);
553 566
554 ret = virt_to_abs(ret); 567 ret = __pa(ret);
555 568
556 dbg("alloc_bootmem %lx %lx\n", ret, size); 569 dbg("alloc_bootmem %lx %lx\n", ret, size);
557 } 570 }
558 571
559 return ret; 572 return (void *)ret;
560} 573}
561 574
562void __init do_init_bootmem(void) 575void __init do_init_bootmem(void)
563{ 576{
564 int nid; 577 int nid;
565 int addr_cells, size_cells; 578 unsigned int i;
566 struct device_node *memory = NULL;
567 static struct notifier_block ppc64_numa_nb = { 579 static struct notifier_block ppc64_numa_nb = {
568 .notifier_call = cpu_numa_callback, 580 .notifier_call = cpu_numa_callback,
569 .priority = 1 /* Must run before sched domains notifier. */ 581 .priority = 1 /* Must run before sched domains notifier. */
@@ -581,99 +593,66 @@ void __init do_init_bootmem(void)
581 register_cpu_notifier(&ppc64_numa_nb); 593 register_cpu_notifier(&ppc64_numa_nb);
582 594
583 for_each_online_node(nid) { 595 for_each_online_node(nid) {
584 unsigned long start_paddr, end_paddr; 596 unsigned long start_pfn, end_pfn, pages_present;
585 int i;
586 unsigned long bootmem_paddr; 597 unsigned long bootmem_paddr;
587 unsigned long bootmap_pages; 598 unsigned long bootmap_pages;
588 599
589 start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE; 600 get_region(nid, &start_pfn, &end_pfn, &pages_present);
590 end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE;
591 601
592 /* Allocate the node structure node local if possible */ 602 /* Allocate the node structure node local if possible */
593 NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid, 603 NODE_DATA(nid) = careful_allocation(nid,
594 sizeof(struct pglist_data), 604 sizeof(struct pglist_data),
595 SMP_CACHE_BYTES, end_paddr); 605 SMP_CACHE_BYTES, end_pfn);
596 NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid)); 606 NODE_DATA(nid) = __va(NODE_DATA(nid));
597 memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); 607 memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
598 608
599 dbg("node %d\n", nid); 609 dbg("node %d\n", nid);
600 dbg("NODE_DATA() = %p\n", NODE_DATA(nid)); 610 dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
601 611
602 NODE_DATA(nid)->bdata = &plat_node_bdata[nid]; 612 NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
603 NODE_DATA(nid)->node_start_pfn = 613 NODE_DATA(nid)->node_start_pfn = start_pfn;
604 init_node_data[nid].node_start_pfn; 614 NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
605 NODE_DATA(nid)->node_spanned_pages =
606 end_paddr - start_paddr;
607 615
608 if (NODE_DATA(nid)->node_spanned_pages == 0) 616 if (NODE_DATA(nid)->node_spanned_pages == 0)
609 continue; 617 continue;
610 618
611 dbg("start_paddr = %lx\n", start_paddr); 619 dbg("start_paddr = %lx\n", start_pfn << PAGE_SHIFT);
612 dbg("end_paddr = %lx\n", end_paddr); 620 dbg("end_paddr = %lx\n", end_pfn << PAGE_SHIFT);
613 621
614 bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT); 622 bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
623 bootmem_paddr = (unsigned long)careful_allocation(nid,
624 bootmap_pages << PAGE_SHIFT,
625 PAGE_SIZE, end_pfn);
626 memset(__va(bootmem_paddr), 0, bootmap_pages << PAGE_SHIFT);
615 627
616 bootmem_paddr = careful_allocation(nid,
617 bootmap_pages << PAGE_SHIFT,
618 PAGE_SIZE, end_paddr);
619 memset(abs_to_virt(bootmem_paddr), 0,
620 bootmap_pages << PAGE_SHIFT);
621 dbg("bootmap_paddr = %lx\n", bootmem_paddr); 628 dbg("bootmap_paddr = %lx\n", bootmem_paddr);
622 629
623 init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, 630 init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
624 start_paddr >> PAGE_SHIFT, 631 start_pfn, end_pfn);
625 end_paddr >> PAGE_SHIFT);
626 632
627 /* 633 /* Add free regions on this node */
628 * We need to do another scan of all memory sections to 634 for (i = 0; init_node_data[i].end_pfn; i++) {
629 * associate memory with the correct node. 635 unsigned long start, end;
630 */
631 addr_cells = get_mem_addr_cells();
632 size_cells = get_mem_size_cells();
633 memory = NULL;
634 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
635 unsigned long mem_start, mem_size;
636 int numa_domain, ranges;
637 unsigned int *memcell_buf;
638 unsigned int len;
639
640 memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
641 if (!memcell_buf || len <= 0)
642 continue;
643 636
644 ranges = memory->n_addrs; /* ranges in cell */ 637 if (init_node_data[i].nid != nid)
645new_range:
646 mem_start = read_n_cells(addr_cells, &memcell_buf);
647 mem_size = read_n_cells(size_cells, &memcell_buf);
648 if (numa_enabled) {
649 numa_domain = of_node_numa_domain(memory);
650 if (numa_domain >= MAX_NUMNODES)
651 numa_domain = 0;
652 } else
653 numa_domain = 0;
654
655 if (numa_domain != nid)
656 continue; 638 continue;
657 639
658 mem_size = numa_enforce_memory_limit(mem_start, mem_size); 640 start = init_node_data[i].start_pfn << PAGE_SHIFT;
659 if (mem_size) { 641 end = init_node_data[i].end_pfn << PAGE_SHIFT;
660 dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
661 free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
662 }
663 642
664 if (--ranges) /* process all ranges in cell */ 643 dbg("free_bootmem %lx %lx\n", start, end - start);
665 goto new_range; 644 free_bootmem_node(NODE_DATA(nid), start, end - start);
666 } 645 }
667 646
668 /* 647 /* Mark reserved regions on this node */
669 * Mark reserved regions on this node
670 */
671 for (i = 0; i < lmb.reserved.cnt; i++) { 648 for (i = 0; i < lmb.reserved.cnt; i++) {
672 unsigned long physbase = lmb.reserved.region[i].base; 649 unsigned long physbase = lmb.reserved.region[i].base;
673 unsigned long size = lmb.reserved.region[i].size; 650 unsigned long size = lmb.reserved.region[i].size;
651 unsigned long start_paddr = start_pfn << PAGE_SHIFT;
652 unsigned long end_paddr = end_pfn << PAGE_SHIFT;
674 653
675 if (pa_to_nid(physbase) != nid && 654 if (early_pfn_to_nid(physbase >> PAGE_SHIFT) != nid &&
676 pa_to_nid(physbase+size-1) != nid) 655 early_pfn_to_nid((physbase+size-1) >> PAGE_SHIFT) != nid)
677 continue; 656 continue;
678 657
679 if (physbase < end_paddr && 658 if (physbase < end_paddr &&
@@ -693,46 +672,19 @@ new_range:
693 size); 672 size);
694 } 673 }
695 } 674 }
696 /*
697 * This loop may look famaliar, but we have to do it again
698 * after marking our reserved memory to mark memory present
699 * for sparsemem.
700 */
701 addr_cells = get_mem_addr_cells();
702 size_cells = get_mem_size_cells();
703 memory = NULL;
704 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
705 unsigned long mem_start, mem_size;
706 int numa_domain, ranges;
707 unsigned int *memcell_buf;
708 unsigned int len;
709
710 memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
711 if (!memcell_buf || len <= 0)
712 continue;
713 675
714 ranges = memory->n_addrs; /* ranges in cell */ 676 /* Add regions into sparsemem */
715new_range2: 677 for (i = 0; init_node_data[i].end_pfn; i++) {
716 mem_start = read_n_cells(addr_cells, &memcell_buf); 678 unsigned long start, end;
717 mem_size = read_n_cells(size_cells, &memcell_buf); 679
718 if (numa_enabled) { 680 if (init_node_data[i].nid != nid)
719 numa_domain = of_node_numa_domain(memory);
720 if (numa_domain >= MAX_NUMNODES)
721 numa_domain = 0;
722 } else
723 numa_domain = 0;
724
725 if (numa_domain != nid)
726 continue; 681 continue;
727 682
728 mem_size = numa_enforce_memory_limit(mem_start, mem_size); 683 start = init_node_data[i].start_pfn;
729 memory_present(numa_domain, mem_start >> PAGE_SHIFT, 684 end = init_node_data[i].end_pfn;
730 (mem_start + mem_size) >> PAGE_SHIFT);
731 685
732 if (--ranges) /* process all ranges in cell */ 686 memory_present(nid, start, end);
733 goto new_range2;
734 } 687 }
735
736 } 688 }
737} 689}
738 690
@@ -746,21 +698,18 @@ void __init paging_init(void)
746 memset(zholes_size, 0, sizeof(zholes_size)); 698 memset(zholes_size, 0, sizeof(zholes_size));
747 699
748 for_each_online_node(nid) { 700 for_each_online_node(nid) {
749 unsigned long start_pfn; 701 unsigned long start_pfn, end_pfn, pages_present;
750 unsigned long end_pfn;
751 702
752 start_pfn = init_node_data[nid].node_start_pfn; 703 get_region(nid, &start_pfn, &end_pfn, &pages_present);
753 end_pfn = init_node_data[nid].node_end_pfn;
754 704
755 zones_size[ZONE_DMA] = end_pfn - start_pfn; 705 zones_size[ZONE_DMA] = end_pfn - start_pfn;
756 zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - 706 zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - pages_present;
757 init_node_data[nid].node_present_pages;
758 707
759 dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid, 708 dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
760 zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]); 709 zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
761 710
762 free_area_init_node(nid, NODE_DATA(nid), zones_size, 711 free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn,
763 start_pfn, zholes_size); 712 zholes_size);
764 } 713 }
765} 714}
766 715
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index e3a024e324b6..a3401b46f3ba 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -14,7 +14,6 @@
14#include <asm/system.h> 14#include <asm/system.h>
15#include <asm/processor.h> 15#include <asm/processor.h>
16#include <asm/cputable.h> 16#include <asm/cputable.h>
17#include <asm/systemcfg.h>
18#include <asm/rtas.h> 17#include <asm/rtas.h>
19#include <asm/oprofile_impl.h> 18#include <asm/oprofile_impl.h>
20#include <asm/reg.h> 19#include <asm/reg.h>
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index 00cf331a1dc4..a6f628d4c9dc 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -27,7 +27,6 @@
27#include <asm/prom.h> 27#include <asm/prom.h>
28#include <asm/nvram.h> 28#include <asm/nvram.h>
29#include <asm/atomic.h> 29#include <asm/atomic.h>
30#include <asm/systemcfg.h>
31 30
32#if 0 31#if 0
33#define DEBUG(A...) printk(KERN_ERR A) 32#define DEBUG(A...) printk(KERN_ERR A)
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index e94247c28d42..31990829310c 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -306,9 +306,7 @@ static void __init fw_feature_init(void)
306 } 306 }
307 307
308 of_node_put(dn); 308 of_node_put(dn);
309 no_rtas: 309no_rtas:
310 printk(KERN_INFO "firmware_features = 0x%lx\n",
311 ppc64_firmware_features);
312 310
313 DBG(" <- fw_feature_init()\n"); 311 DBG(" <- fw_feature_init()\n");
314} 312}
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 3ba794ca3288..5800cde7d5ad 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -46,7 +46,7 @@
46#include <asm/rtas.h> 46#include <asm/rtas.h>
47#include <asm/pSeries_reconfig.h> 47#include <asm/pSeries_reconfig.h>
48#include <asm/mpic.h> 48#include <asm/mpic.h>
49#include <asm/systemcfg.h> 49#include <asm/vdso_datapage.h>
50 50
51#include "plpar_wrappers.h" 51#include "plpar_wrappers.h"
52 52
@@ -97,7 +97,7 @@ int pSeries_cpu_disable(void)
97 int cpu = smp_processor_id(); 97 int cpu = smp_processor_id();
98 98
99 cpu_clear(cpu, cpu_online_map); 99 cpu_clear(cpu, cpu_online_map);
100 _systemcfg->processorCount--; 100 vdso_data->processorCount--;
101 101
102 /*fix boot_cpuid here*/ 102 /*fix boot_cpuid here*/
103 if (cpu == boot_cpuid) 103 if (cpu == boot_cpuid)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index cfcb2a56d662..ef4356b29a97 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -1467,17 +1467,23 @@ read_spr(int n)
1467{ 1467{
1468 unsigned int instrs[2]; 1468 unsigned int instrs[2];
1469 unsigned long (*code)(void); 1469 unsigned long (*code)(void);
1470 unsigned long opd[3];
1471 unsigned long ret = -1UL; 1470 unsigned long ret = -1UL;
1471#ifdef CONFIG_PPC64
1472 unsigned long opd[3];
1472 1473
1473 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1474 instrs[1] = 0x4e800020;
1475 opd[0] = (unsigned long)instrs; 1474 opd[0] = (unsigned long)instrs;
1476 opd[1] = 0; 1475 opd[1] = 0;
1477 opd[2] = 0; 1476 opd[2] = 0;
1477 code = (unsigned long (*)(void)) opd;
1478#else
1479 code = (unsigned long (*)(void)) instrs;
1480#endif
1481
1482 /* mfspr r3,n; blr */
1483 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1484 instrs[1] = 0x4e800020;
1478 store_inst(instrs); 1485 store_inst(instrs);
1479 store_inst(instrs+1); 1486 store_inst(instrs+1);
1480 code = (unsigned long (*)(void)) opd;
1481 1487
1482 if (setjmp(bus_error_jmp) == 0) { 1488 if (setjmp(bus_error_jmp) == 0) {
1483 catch_memory_errors = 1; 1489 catch_memory_errors = 1;
@@ -1499,16 +1505,21 @@ write_spr(int n, unsigned long val)
1499{ 1505{
1500 unsigned int instrs[2]; 1506 unsigned int instrs[2];
1501 unsigned long (*code)(unsigned long); 1507 unsigned long (*code)(unsigned long);
1508#ifdef CONFIG_PPC64
1502 unsigned long opd[3]; 1509 unsigned long opd[3];
1503 1510
1504 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1505 instrs[1] = 0x4e800020;
1506 opd[0] = (unsigned long)instrs; 1511 opd[0] = (unsigned long)instrs;
1507 opd[1] = 0; 1512 opd[1] = 0;
1508 opd[2] = 0; 1513 opd[2] = 0;
1514 code = (unsigned long (*)(unsigned long)) opd;
1515#else
1516 code = (unsigned long (*)(unsigned long)) instrs;
1517#endif
1518
1519 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1520 instrs[1] = 0x4e800020;
1509 store_inst(instrs); 1521 store_inst(instrs);
1510 store_inst(instrs+1); 1522 store_inst(instrs+1);
1511 code = (unsigned long (*)(unsigned long)) opd;
1512 1523
1513 if (setjmp(bus_error_jmp) == 0) { 1524 if (setjmp(bus_error_jmp) == 0) {
1514 catch_memory_errors = 1; 1525 catch_memory_errors = 1;
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 968261d69572..fe0e767fb94e 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -25,6 +25,7 @@
25#include <asm/processor.h> 25#include <asm/processor.h>
26#include <asm/cputable.h> 26#include <asm/cputable.h>
27#include <asm/thread_info.h> 27#include <asm/thread_info.h>
28#include <asm/vdso_datapage.h>
28 29
29#define DEFINE(sym, val) \ 30#define DEFINE(sym, val) \
30 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 31 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -143,5 +144,32 @@ main(void)
143 144
144 DEFINE(TASK_SIZE, TASK_SIZE); 145 DEFINE(TASK_SIZE, TASK_SIZE);
145 DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); 146 DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
147
148 /* datapage offsets for use by vdso */
149 DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct vdso_data, tb_orig_stamp));
150 DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct vdso_data, tb_ticks_per_sec));
151 DEFINE(CFG_TB_TO_XS, offsetof(struct vdso_data, tb_to_xs));
152 DEFINE(CFG_STAMP_XSEC, offsetof(struct vdso_data, stamp_xsec));
153 DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct vdso_data, tb_update_count));
154 DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct vdso_data, tz_minuteswest));
155 DEFINE(CFG_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
156 DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
157 DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
158 DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
159 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec));
160 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec));
161 DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec));
162 DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec));
163
164 /* timeval/timezone offsets for use by vdso */
165 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
166 DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
167
168 /* Other bits used by the vdso */
169 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
170 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
171 DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
172 DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
173
146 return 0; 174 return 0;
147} 175}
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index c867be6981cb..29d95d415ceb 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -37,7 +37,7 @@ static u_char irq_to_siureg[] = {
37static u_char irq_to_siubit[] = { 37static u_char irq_to_siubit[] = {
38 0, 15, 14, 13, 12, 11, 10, 9, 38 0, 15, 14, 13, 12, 11, 10, 9,
39 8, 7, 6, 5, 4, 3, 2, 1, 39 8, 7, 6, 5, 4, 3, 2, 1,
40 2, 1, 15, 14, 13, 12, 11, 10, 40 2, 1, 0, 14, 13, 12, 11, 10,
41 9, 8, 7, 6, 5, 4, 3, 0, 41 9, 8, 7, 6, 5, 4, 3, 0,
42 31, 30, 29, 28, 27, 26, 25, 24, 42 31, 30, 29, 28, 27, 26, 25, 24,
43 23, 22, 21, 20, 19, 18, 17, 16, 43 23, 22, 21, 20, 19, 18, 17, 16,
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index c9d32db9d76a..9d10c12e87fe 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -279,17 +279,12 @@ config ARCH_FLATMEM_ENABLE
279 def_bool y 279 def_bool y
280 depends on !NUMA 280 depends on !NUMA
281 281
282config ARCH_DISCONTIGMEM_ENABLE 282config ARCH_SPARSEMEM_ENABLE
283 def_bool y
284 depends on SMP && PPC_PSERIES
285
286config ARCH_DISCONTIGMEM_DEFAULT
287 def_bool y 283 def_bool y
288 depends on ARCH_DISCONTIGMEM_ENABLE
289 284
290config ARCH_SPARSEMEM_ENABLE 285config ARCH_SPARSEMEM_DEFAULT
291 def_bool y 286 def_bool y
292 depends on ARCH_DISCONTIGMEM_ENABLE 287 depends on NUMA
293 288
294source "mm/Kconfig" 289source "mm/Kconfig"
295 290
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 58b19f107656..dac4cc20fa93 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -13,10 +13,8 @@ endif
13 13
14obj-y += idle.o dma.o \ 14obj-y += idle.o dma.o \
15 align.o \ 15 align.o \
16 udbg.o \
17 rtc.o \ 16 rtc.o \
18 iommu.o vdso.o 17 iommu.o
19obj-y += vdso32/ vdso64/
20 18
21pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o 19pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
22 20
@@ -27,8 +25,6 @@ ifneq ($(CONFIG_PPC_MERGE),y)
27obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o 25obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
28endif 26endif
29 27
30obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
31
32obj-$(CONFIG_KEXEC) += machine_kexec.o 28obj-$(CONFIG_KEXEC) += machine_kexec.o
33obj-$(CONFIG_MODULES) += module.o 29obj-$(CONFIG_MODULES) += module.o
34ifneq ($(CONFIG_PPC_MERGE),y) 30ifneq ($(CONFIG_PPC_MERGE),y)
@@ -40,10 +36,6 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
40endif 36endif
41obj-$(CONFIG_HVCS) += hvcserver.o 37obj-$(CONFIG_HVCS) += hvcserver.o
42 38
43obj-$(CONFIG_PPC_PMAC) += udbg_scc.o
44
45obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
46
47obj-$(CONFIG_KPROBES) += kprobes.o 39obj-$(CONFIG_KPROBES) += kprobes.o
48 40
49ifneq ($(CONFIG_PPC_MERGE),y) 41ifneq ($(CONFIG_PPC_MERGE),y)
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index 492bca6137eb..5e089deb0a2b 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -186,7 +186,8 @@ _KPROBE(__flush_icache_range)
186 bdnz 2b 186 bdnz 2b
187 isync 187 isync
188 blr 188 blr
189 .previous .text 189
190 .text
190/* 191/*
191 * Like above, but only do the D-cache. 192 * Like above, but only do the D-cache.
192 * 193 *
diff --git a/arch/ppc64/kernel/vdso32/gettimeofday.S b/arch/ppc64/kernel/vdso32/gettimeofday.S
deleted file mode 100644
index e243c1d24af7..000000000000
--- a/arch/ppc64/kernel/vdso32/gettimeofday.S
+++ /dev/null
@@ -1,140 +0,0 @@
1/*
2 * Userland implementation of gettimeofday() for 32 bits processes in a
3 * ppc64 kernel for use in the vDSO
4 *
5 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12#include <linux/config.h>
13#include <asm/processor.h>
14#include <asm/ppc_asm.h>
15#include <asm/vdso.h>
16#include <asm/asm-offsets.h>
17#include <asm/unistd.h>
18
19 .text
20/*
21 * Exact prototype of gettimeofday
22 *
23 * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
24 *
25 */
26V_FUNCTION_BEGIN(__kernel_gettimeofday)
27 .cfi_startproc
28 mflr r12
29 .cfi_register lr,r12
30
31 mr r10,r3 /* r10 saves tv */
32 mr r11,r4 /* r11 saves tz */
33 bl __get_datapage@local /* get data page */
34 mr r9, r3 /* datapage ptr in r9 */
35 bl __do_get_xsec@local /* get xsec from tb & kernel */
36 bne- 2f /* out of line -> do syscall */
37
38 /* seconds are xsec >> 20 */
39 rlwinm r5,r4,12,20,31
40 rlwimi r5,r3,12,0,19
41 stw r5,TVAL32_TV_SEC(r10)
42
43 /* get remaining xsec and convert to usec. we scale
44 * up remaining xsec by 12 bits and get the top 32 bits
45 * of the multiplication
46 */
47 rlwinm r5,r4,12,0,19
48 lis r6,1000000@h
49 ori r6,r6,1000000@l
50 mulhwu r5,r5,r6
51 stw r5,TVAL32_TV_USEC(r10)
52
53 cmpli cr0,r11,0 /* check if tz is NULL */
54 beq 1f
55 lwz r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
56 lwz r5,CFG_TZ_DSTTIME(r9)
57 stw r4,TZONE_TZ_MINWEST(r11)
58 stw r5,TZONE_TZ_DSTTIME(r11)
59
601: mtlr r12
61 li r3,0
62 blr
63
642: mr r3,r10
65 mr r4,r11
66 li r0,__NR_gettimeofday
67 sc
68 b 1b
69 .cfi_endproc
70V_FUNCTION_END(__kernel_gettimeofday)
71
72/*
73 * This is the core of gettimeofday(), it returns the xsec
74 * value in r3 & r4 and expects the datapage ptr (non clobbered)
75 * in r9. clobbers r0,r4,r5,r6,r7,r8
76*/
77__do_get_xsec:
78 .cfi_startproc
79 /* Check for update count & load values. We use the low
80 * order 32 bits of the update count
81 */
821: lwz r8,(CFG_TB_UPDATE_COUNT+4)(r9)
83 andi. r0,r8,1 /* pending update ? loop */
84 bne- 1b
85 xor r0,r8,r8 /* create dependency */
86 add r9,r9,r0
87
88 /* Load orig stamp (offset to TB) */
89 lwz r5,CFG_TB_ORIG_STAMP(r9)
90 lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
91
92 /* Get a stable TB value */
932: mftbu r3
94 mftbl r4
95 mftbu r0
96 cmpl cr0,r3,r0
97 bne- 2b
98
99 /* Substract tb orig stamp. If the high part is non-zero, we jump to the
100 * slow path which call the syscall. If it's ok, then we have our 32 bits
101 * tb_ticks value in r7
102 */
103 subfc r7,r6,r4
104 subfe. r0,r5,r3
105 bne- 3f
106
107 /* Load scale factor & do multiplication */
108 lwz r5,CFG_TB_TO_XS(r9) /* load values */
109 lwz r6,(CFG_TB_TO_XS+4)(r9)
110 mulhwu r4,r7,r5
111 mulhwu r6,r7,r6
112 mullw r0,r7,r5
113 addc r6,r6,r0
114
115 /* At this point, we have the scaled xsec value in r4 + XER:CA
116 * we load & add the stamp since epoch
117 */
118 lwz r5,CFG_STAMP_XSEC(r9)
119 lwz r6,(CFG_STAMP_XSEC+4)(r9)
120 adde r4,r4,r6
121 addze r3,r5
122
123 /* We now have our result in r3,r4. We create a fake dependency
124 * on that result and re-check the counter
125 */
126 xor r0,r4,r4
127 add r9,r9,r0
128 lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
129 cmpl cr0,r8,r0 /* check if updated */
130 bne- 1b
131
132 /* Warning ! The caller expects CR:EQ to be set to indicate a
133 * successful calculation (so it won't fallback to the syscall
134 * method). We have overriden that CR bit in the counter check,
135 * but fortunately, the loop exit condition _is_ CR:EQ set, so
136 * we can exit safely here. If you change this code, be careful
137 * of that side effect.
138 */
1393: blr
140 .cfi_endproc
diff --git a/arch/ppc64/kernel/vdso64/gettimeofday.S b/arch/ppc64/kernel/vdso64/gettimeofday.S
deleted file mode 100644
index f6df8028570a..000000000000
--- a/arch/ppc64/kernel/vdso64/gettimeofday.S
+++ /dev/null
@@ -1,91 +0,0 @@
1/*
2 * Userland implementation of gettimeofday() for 64 bits processes in a
3 * ppc64 kernel for use in the vDSO
4 *
5 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
6 * IBM Corp.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <linux/config.h>
14#include <asm/processor.h>
15#include <asm/ppc_asm.h>
16#include <asm/vdso.h>
17#include <asm/asm-offsets.h>
18
19 .text
20/*
21 * Exact prototype of gettimeofday
22 *
23 * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
24 *
25 */
26V_FUNCTION_BEGIN(__kernel_gettimeofday)
27 .cfi_startproc
28 mflr r12
29 .cfi_register lr,r12
30
31 mr r11,r3 /* r11 holds tv */
32 mr r10,r4 /* r10 holds tz */
33 bl V_LOCAL_FUNC(__get_datapage) /* get data page */
34 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
35 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
36 ori r7,r7,16960
37 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
38 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
39 std r5,TVAL64_TV_SEC(r11) /* store sec in tv */
40 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
41 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / XSEC_PER_SEC */
42 rldicl r0,r0,44,20
43 cmpldi cr0,r10,0 /* check if tz is NULL */
44 std r0,TVAL64_TV_USEC(r11) /* store usec in tv */
45 beq 1f
46 lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
47 lwz r5,CFG_TZ_DSTTIME(r3)
48 stw r4,TZONE_TZ_MINWEST(r10)
49 stw r5,TZONE_TZ_DSTTIME(r10)
501: mtlr r12
51 li r3,0 /* always success */
52 blr
53 .cfi_endproc
54V_FUNCTION_END(__kernel_gettimeofday)
55
56
57/*
58 * This is the core of gettimeofday(), it returns the xsec
59 * value in r4 and expects the datapage ptr (non clobbered)
60 * in r3. clobbers r0,r4,r5,r6,r7,r8
61*/
62V_FUNCTION_BEGIN(__do_get_xsec)
63 .cfi_startproc
64 /* check for update count & load values */
651: ld r7,CFG_TB_UPDATE_COUNT(r3)
66 andi. r0,r4,1 /* pending update ? loop */
67 bne- 1b
68 xor r0,r4,r4 /* create dependency */
69 add r3,r3,r0
70
71 /* Get TB & offset it */
72 mftb r8
73 ld r9,CFG_TB_ORIG_STAMP(r3)
74 subf r8,r9,r8
75
76 /* Scale result */
77 ld r5,CFG_TB_TO_XS(r3)
78 mulhdu r8,r8,r5
79
80 /* Add stamp since epoch */
81 ld r6,CFG_STAMP_XSEC(r3)
82 add r4,r6,r8
83
84 xor r0,r4,r4
85 add r3,r3,r0
86 ld r0,CFG_TB_UPDATE_COUNT(r3)
87 cmpld cr0,r0,r7 /* check if updated */
88 bne- 1b
89 blr
90 .cfi_endproc
91V_FUNCTION_END(__do_get_xsec)
diff --git a/include/asm-powerpc/auxvec.h b/include/asm-powerpc/auxvec.h
index 79d8c4732309..19a099b62cd6 100644
--- a/include/asm-powerpc/auxvec.h
+++ b/include/asm-powerpc/auxvec.h
@@ -14,8 +14,6 @@
14/* The vDSO location. We have to use the same value as x86 for glibc's 14/* The vDSO location. We have to use the same value as x86 for glibc's
15 * sake :-) 15 * sake :-)
16 */ 16 */
17#ifdef __powerpc64__
18#define AT_SYSINFO_EHDR 33 17#define AT_SYSINFO_EHDR 33
19#endif
20 18
21#endif 19#endif
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index feac3458d71f..3dcd65edf978 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -269,14 +269,12 @@ extern int dcache_bsize;
269extern int icache_bsize; 269extern int icache_bsize;
270extern int ucache_bsize; 270extern int ucache_bsize;
271 271
272#ifdef __powerpc64__ 272/* vDSO has arch_setup_additional_pages */
273#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
273struct linux_binprm; 274struct linux_binprm;
274#define ARCH_HAS_SETUP_ADDITIONAL_PAGES /* vDSO has arch_setup_additional_pages */ 275extern int arch_setup_additional_pages(struct linux_binprm *bprm,
275extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack); 276 int executable_stack);
276#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b); 277#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
277#else
278#define VDSO_AUX_ENT(a,b)
279#endif /* __powerpc64__ */
280 278
281/* 279/*
282 * The requirements here are: 280 * The requirements here are:
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index c9fbcede0ef9..8eb7e857ec4c 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -389,6 +389,7 @@ extern u64 ppc64_interrupt_controller;
389#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET) 389#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET)
390#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET) 390#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET)
391#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET) 391#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET)
392#define SIU_INT_PCI ((uint)0x12 + CPM_IRQ_OFFSET)
392#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET) 393#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
393#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET) 394#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET)
394#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET) 395#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET)
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index f6f186b56b0f..d12382d292d4 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -177,8 +177,8 @@ struct thread_struct {
177#ifdef CONFIG_PPC64 177#ifdef CONFIG_PPC64
178 unsigned long start_tb; /* Start purr when proc switched in */ 178 unsigned long start_tb; /* Start purr when proc switched in */
179 unsigned long accum_tb; /* Total accumilated purr for process */ 179 unsigned long accum_tb; /* Total accumilated purr for process */
180 unsigned long vdso_base; /* base of the vDSO library */
181#endif 180#endif
181 unsigned long vdso_base; /* base of the vDSO library */
182 unsigned long dabr; /* Data address breakpoint register */ 182 unsigned long dabr; /* Data address breakpoint register */
183#ifdef CONFIG_ALTIVEC 183#ifdef CONFIG_ALTIVEC
184 /* Complete AltiVec register set */ 184 /* Complete AltiVec register set */
diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h
index 58d2aab416f8..ba1b34fdb967 100644
--- a/include/asm-powerpc/sparsemem.h
+++ b/include/asm-powerpc/sparsemem.h
@@ -8,8 +8,8 @@
8 * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space 8 * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
9 */ 9 */
10#define SECTION_SIZE_BITS 24 10#define SECTION_SIZE_BITS 24
11#define MAX_PHYSADDR_BITS 38 11#define MAX_PHYSADDR_BITS 44
12#define MAX_PHYSMEM_BITS 36 12#define MAX_PHYSMEM_BITS 44
13 13
14#ifdef CONFIG_MEMORY_HOTPLUG 14#ifdef CONFIG_MEMORY_HOTPLUG
15extern void create_section_mapping(unsigned long start, unsigned long end); 15extern void create_section_mapping(unsigned long start, unsigned long end);
diff --git a/include/asm-powerpc/systemcfg.h b/include/asm-powerpc/systemcfg.h
deleted file mode 100644
index 36b5cbe466f1..000000000000
--- a/include/asm-powerpc/systemcfg.h
+++ /dev/null
@@ -1,64 +0,0 @@
1#ifndef _SYSTEMCFG_H
2#define _SYSTEMCFG_H
3
4/*
5 * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13/* Change Activity:
14 * 2002/09/30 : bergner : Created
15 * End Change Activity
16 */
17
18/*
19 * If the major version changes we are incompatible.
20 * Minor version changes are a hint.
21 */
22#define SYSTEMCFG_MAJOR 1
23#define SYSTEMCFG_MINOR 1
24
25#ifndef __ASSEMBLY__
26
27#include <linux/unistd.h>
28
29#define SYSCALL_MAP_SIZE ((__NR_syscalls + 31) / 32)
30
31struct systemcfg {
32 __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
33 struct { /* Systemcfg version numbers */
34 __u32 major; /* Major number 0x10 */
35 __u32 minor; /* Minor number 0x14 */
36 } version;
37
38 __u32 platform; /* Platform flags 0x18 */
39 __u32 processor; /* Processor type 0x1C */
40 __u64 processorCount; /* # of physical processors 0x20 */
41 __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
42 __u64 tb_orig_stamp; /* Timebase at boot 0x30 */
43 __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
44 __u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
45 __u64 stamp_xsec; /* 0x48 */
46 __u64 tb_update_count; /* Timebase atomicity ctr 0x50 */
47 __u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
48 __u32 tz_dsttime; /* Type of dst correction 0x5C */
49 /* next four are no longer used except to be exported to /proc */
50 __u32 dcache_size; /* L1 d-cache size 0x60 */
51 __u32 dcache_line_size; /* L1 d-cache line size 0x64 */
52 __u32 icache_size; /* L1 i-cache size 0x68 */
53 __u32 icache_line_size; /* L1 i-cache line size 0x6C */
54 __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of available syscalls 0x70 */
55 __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of available syscalls */
56};
57
58#ifdef __KERNEL__
59extern struct systemcfg *_systemcfg; /* to be renamed */
60#endif
61
62#endif /* __ASSEMBLY__ */
63
64#endif /* _SYSTEMCFG_H */
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index 2512e3836bf4..015d28746e1b 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -9,15 +9,7 @@
9 9
10static inline int cpu_to_node(int cpu) 10static inline int cpu_to_node(int cpu)
11{ 11{
12 int node; 12 return numa_cpu_lookup_table[cpu];
13
14 node = numa_cpu_lookup_table[cpu];
15
16#ifdef DEBUG_NUMA
17 BUG_ON(node == -1);
18#endif
19
20 return node;
21} 13}
22 14
23#define parent_node(node) (node) 15#define parent_node(node) (node)
@@ -37,8 +29,6 @@ static inline int node_to_first_cpu(int node)
37#define pcibus_to_node(node) (-1) 29#define pcibus_to_node(node) (-1)
38#define pcibus_to_cpumask(bus) (cpu_online_map) 30#define pcibus_to_cpumask(bus) (cpu_online_map)
39 31
40#define nr_cpus_node(node) (nr_cpus_in_node[node])
41
42/* sched_domains SD_NODE_INIT for PPC64 machines */ 32/* sched_domains SD_NODE_INIT for PPC64 machines */
43#define SD_NODE_INIT (struct sched_domain) { \ 33#define SD_NODE_INIT (struct sched_domain) { \
44 .span = CPU_MASK_NONE, \ 34 .span = CPU_MASK_NONE, \
diff --git a/include/asm-ppc64/udbg.h b/include/asm-powerpc/udbg.h
index e3b927991851..a383383bc4d4 100644
--- a/include/asm-ppc64/udbg.h
+++ b/include/asm-powerpc/udbg.h
@@ -1,9 +1,3 @@
1#ifndef __UDBG_HDR
2#define __UDBG_HDR
3
4#include <linux/compiler.h>
5#include <linux/init.h>
6
7/* 1/*
8 * c 2001 PPC 64 Team, IBM Corp 2 * c 2001 PPC 64 Team, IBM Corp
9 * 3 *
@@ -13,6 +7,12 @@
13 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
14 */ 8 */
15 9
10#ifndef _ASM_POWERPC_UDBG_H
11#define _ASM_POWERPC_UDBG_H
12
13#include <linux/compiler.h>
14#include <linux/init.h>
15
16extern void (*udbg_putc)(unsigned char c); 16extern void (*udbg_putc)(unsigned char c);
17extern unsigned char (*udbg_getc)(void); 17extern unsigned char (*udbg_getc)(void);
18extern int (*udbg_getc_poll)(void); 18extern int (*udbg_getc_poll)(void);
@@ -28,4 +28,4 @@ extern void udbg_init_uart(void __iomem *comport, unsigned int speed);
28 28
29struct device_node; 29struct device_node;
30extern void udbg_init_scc(struct device_node *np); 30extern void udbg_init_scc(struct device_node *np);
31#endif 31#endif /* _ASM_POWERPC_UDBG_H */
diff --git a/include/asm-ppc64/vdso.h b/include/asm-powerpc/vdso.h
index 85d8a7be25c4..85d8a7be25c4 100644
--- a/include/asm-ppc64/vdso.h
+++ b/include/asm-powerpc/vdso.h
diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h
new file mode 100644
index 000000000000..fc323b51366b
--- /dev/null
+++ b/include/asm-powerpc/vdso_datapage.h
@@ -0,0 +1,108 @@
1#ifndef _VDSO_DATAPAGE_H
2#define _VDSO_DATAPAGE_H
3
4/*
5 * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
6 * Copyright (C) 2005 Benjamin Herrenschmidy <benh@kernel.crashing.org>,
7 * IBM Corp.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15
16/*
17 * Note about this structure:
18 *
19 * This structure was historically called systemcfg and exposed to
20 * userland via /proc/ppc64/systemcfg. Unfortunately, this became an
21 * ABI issue as some proprietary software started relying on being able
22 * to mmap() it, thus we have to keep the base layout at least for a
23 * few kernel versions.
24 *
25 * However, since ppc32 doesn't suffer from this backward handicap,
26 * a simpler version of the data structure is used there with only the
27 * fields actually used by the vDSO.
28 *
29 */
30
31/*
32 * If the major version changes we are incompatible.
33 * Minor version changes are a hint.
34 */
35#define SYSTEMCFG_MAJOR 1
36#define SYSTEMCFG_MINOR 1
37
38#ifndef __ASSEMBLY__
39
40#include <linux/unistd.h>
41
42#define SYSCALL_MAP_SIZE ((__NR_syscalls + 31) / 32)
43
44/*
45 * So here is the ppc64 backward compatible version
46 */
47
48#ifdef CONFIG_PPC64
49
50struct vdso_data {
51 __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
52 struct { /* Systemcfg version numbers */
53 __u32 major; /* Major number 0x10 */
54 __u32 minor; /* Minor number 0x14 */
55 } version;
56
57 __u32 platform; /* Platform flags 0x18 */
58 __u32 processor; /* Processor type 0x1C */
59 __u64 processorCount; /* # of physical processors 0x20 */
60 __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
61 __u64 tb_orig_stamp; /* Timebase at boot 0x30 */
62 __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
63 __u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
64 __u64 stamp_xsec; /* 0x48 */
65 __u64 tb_update_count; /* Timebase atomicity ctr 0x50 */
66 __u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
67 __u32 tz_dsttime; /* Type of dst correction 0x5C */
68 __u32 dcache_size; /* L1 d-cache size 0x60 */
69 __u32 dcache_line_size; /* L1 d-cache line size 0x64 */
70 __u32 icache_size; /* L1 i-cache size 0x68 */
71 __u32 icache_line_size; /* L1 i-cache line size 0x6C */
72
73 /* those additional ones don't have to be located anywhere
74 * special as they were not part of the original systemcfg
75 */
76 __s64 wtom_clock_sec; /* Wall to monotonic clock */
77 __s32 wtom_clock_nsec;
78 __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */
79 __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
80};
81
82#else /* CONFIG_PPC64 */
83
84/*
85 * And here is the simpler 32 bits version
86 */
87struct vdso_data {
88 __u64 tb_orig_stamp; /* Timebase at boot 0x30 */
89 __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
90 __u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
91 __u64 stamp_xsec; /* 0x48 */
92 __u32 tb_update_count; /* Timebase atomicity ctr 0x50 */
93 __u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
94 __u32 tz_dsttime; /* Type of dst correction 0x5C */
95 __s32 wtom_clock_sec; /* Wall to monotonic clock */
96 __s32 wtom_clock_nsec;
97 __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
98};
99
100#endif /* CONFIG_PPC64 */
101
102#ifdef __KERNEL__
103extern struct vdso_data *vdso_data;
104#endif
105
106#endif /* __ASSEMBLY__ */
107
108#endif /* _SYSTEMCFG_H */
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
index fc44f7ca62d7..538e0c8ab243 100644
--- a/include/asm-ppc/page.h
+++ b/include/asm-ppc/page.h
@@ -1,9 +1,12 @@
1#ifndef _PPC_PAGE_H 1#ifndef _PPC_PAGE_H
2#define _PPC_PAGE_H 2#define _PPC_PAGE_H
3 3
4#include <linux/config.h>
5#include <asm/asm-compat.h>
6
4/* PAGE_SHIFT determines the page size */ 7/* PAGE_SHIFT determines the page size */
5#define PAGE_SHIFT 12 8#define PAGE_SHIFT 12
6#define PAGE_SIZE (1UL << PAGE_SHIFT) 9#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
7 10
8/* 11/*
9 * Subtle: this is an int (not an unsigned long) and so it 12 * Subtle: this is an int (not an unsigned long) and so it
@@ -169,5 +172,8 @@ extern __inline__ int get_order(unsigned long size)
169#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 172#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
170 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 173 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
171 174
175/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
176#define __HAVE_ARCH_GATE_AREA 1
177
172#endif /* __KERNEL__ */ 178#endif /* __KERNEL__ */
173#endif /* _PPC_PAGE_H */ 179#endif /* _PPC_PAGE_H */
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
index 15e777ce0f4a..54958d6cae04 100644
--- a/include/asm-ppc64/mmzone.h
+++ b/include/asm-ppc64/mmzone.h
@@ -8,15 +8,14 @@
8#define _ASM_MMZONE_H_ 8#define _ASM_MMZONE_H_
9 9
10#include <linux/config.h> 10#include <linux/config.h>
11#include <asm/smp.h>
12 11
13/* generic non-linear memory support: 12/*
13 * generic non-linear memory support:
14 * 14 *
15 * 1) we will not split memory into more chunks than will fit into the 15 * 1) we will not split memory into more chunks than will fit into the
16 * flags field of the struct page 16 * flags field of the struct page
17 */ 17 */
18 18
19
20#ifdef CONFIG_NEED_MULTIPLE_NODES 19#ifdef CONFIG_NEED_MULTIPLE_NODES
21 20
22extern struct pglist_data *node_data[]; 21extern struct pglist_data *node_data[];
@@ -30,44 +29,11 @@ extern struct pglist_data *node_data[];
30 */ 29 */
31 30
32extern int numa_cpu_lookup_table[]; 31extern int numa_cpu_lookup_table[];
33extern char *numa_memory_lookup_table;
34extern cpumask_t numa_cpumask_lookup_table[]; 32extern cpumask_t numa_cpumask_lookup_table[];
35extern int nr_cpus_in_node[];
36#ifdef CONFIG_MEMORY_HOTPLUG 33#ifdef CONFIG_MEMORY_HOTPLUG
37extern unsigned long max_pfn; 34extern unsigned long max_pfn;
38#endif 35#endif
39 36
40/* 16MB regions */
41#define MEMORY_INCREMENT_SHIFT 24
42#define MEMORY_INCREMENT (1UL << MEMORY_INCREMENT_SHIFT)
43
44/* NUMA debugging, will not work on a DLPAR machine */
45#undef DEBUG_NUMA
46
47static inline int pa_to_nid(unsigned long pa)
48{
49 int nid;
50
51#ifdef CONFIG_MEMORY_HOTPLUG
52 /* kludge hot added sections default to node 0 */
53 if (pa >= (max_pfn << PAGE_SHIFT))
54 return 0;
55#endif
56 nid = numa_memory_lookup_table[pa >> MEMORY_INCREMENT_SHIFT];
57
58#ifdef DEBUG_NUMA
59 /* the physical address passed in is not in the map for the system */
60 if (nid == -1) {
61 printk("bad address: %lx\n", pa);
62 BUG();
63 }
64#endif
65
66 return nid;
67}
68
69#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
70
71/* 37/*
72 * Following are macros that each numa implmentation must define. 38 * Following are macros that each numa implmentation must define.
73 */ 39 */
@@ -75,39 +41,10 @@ static inline int pa_to_nid(unsigned long pa)
75#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) 41#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
76#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) 42#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn)
77 43
78#ifdef CONFIG_DISCONTIGMEM
79
80/*
81 * Given a kernel address, find the home node of the underlying memory.
82 */
83#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
84
85#define pfn_to_nid(pfn) pa_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
86
87/* Written this way to avoid evaluating arguments twice */
88#define discontigmem_pfn_to_page(pfn) \
89({ \
90 unsigned long __tmp = pfn; \
91 (NODE_DATA(pfn_to_nid(__tmp))->node_mem_map + \
92 node_localnr(__tmp, pfn_to_nid(__tmp))); \
93})
94
95#define discontigmem_page_to_pfn(p) \
96({ \
97 struct page *__tmp = p; \
98 (((__tmp) - page_zone(__tmp)->zone_mem_map) + \
99 page_zone(__tmp)->zone_start_pfn); \
100})
101
102/* XXX fix for discontiguous physical memory */
103#define discontigmem_pfn_valid(pfn) ((pfn) < num_physpages)
104
105#endif /* CONFIG_DISCONTIGMEM */
106
107#endif /* CONFIG_NEED_MULTIPLE_NODES */ 44#endif /* CONFIG_NEED_MULTIPLE_NODES */
108 45
109#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID 46#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
110#define early_pfn_to_nid(pfn) pa_to_nid(((unsigned long)pfn) << PAGE_SHIFT) 47extern int __init early_pfn_to_nid(unsigned long pfn);
111#endif 48#endif
112 49
113#endif /* _ASM_MMZONE_H_ */ 50#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index e32f1187aa29..3efc3288f7e9 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -279,11 +279,6 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
279 279
280#define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) 280#define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
281 281
282#ifdef CONFIG_DISCONTIGMEM
283#define page_to_pfn(page) discontigmem_page_to_pfn(page)
284#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn)
285#define pfn_valid(pfn) discontigmem_pfn_valid(pfn)
286#endif
287#ifdef CONFIG_FLATMEM 282#ifdef CONFIG_FLATMEM
288#define pfn_to_page(pfn) (mem_map + (pfn)) 283#define pfn_to_page(pfn) (mem_map + (pfn))
289#define page_to_pfn(page) ((unsigned long)((page) - mem_map)) 284#define page_to_pfn(page) ((unsigned long)((page) - mem_map))