aboutsummaryrefslogtreecommitdiff
path: root/arch/ppc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel')
-rw-r--r--arch/ppc64/kernel/ItLpQueue.c294
-rw-r--r--arch/ppc64/kernel/LparData.c11
-rw-r--r--arch/ppc64/kernel/cpu_setup_power4.S38
-rw-r--r--arch/ppc64/kernel/cputable.c380
-rw-r--r--arch/ppc64/kernel/head.S10
-rw-r--r--arch/ppc64/kernel/hvconsole.c51
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c51
-rw-r--r--arch/ppc64/kernel/iSeries_proc.c48
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c137
-rw-r--r--arch/ppc64/kernel/idle.c283
-rw-r--r--arch/ppc64/kernel/irq.c9
-rw-r--r--arch/ppc64/kernel/kprobes.c125
-rw-r--r--arch/ppc64/kernel/maple_setup.c3
-rw-r--r--arch/ppc64/kernel/mf.c6
-rw-r--r--arch/ppc64/kernel/misc.S6
-rw-r--r--arch/ppc64/kernel/nvram.c8
-rw-r--r--arch/ppc64/kernel/of_device.c15
-rw-r--r--arch/ppc64/kernel/pSeries_lpar.c47
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c156
-rw-r--r--arch/ppc64/kernel/pacaData.c212
-rw-r--r--arch/ppc64/kernel/pci.c22
-rw-r--r--arch/ppc64/kernel/pmac_setup.c5
-rw-r--r--arch/ppc64/kernel/ppc_ksyms.c1
-rw-r--r--arch/ppc64/kernel/process.c4
-rw-r--r--arch/ppc64/kernel/setup.c8
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c54
-rw-r--r--arch/ppc64/kernel/sysfs.c21
-rw-r--r--arch/ppc64/kernel/time.c9
-rw-r--r--arch/ppc64/kernel/vdso32/vdso32.lds.S4
29 files changed, 1032 insertions, 986 deletions
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index cdea00d7707..4231861288a 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -1,7 +1,7 @@
/*
* ItLpQueue.c
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -11,156 +11,252 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
#include <asm/system.h>
#include <asm/paca.h>
#include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvCallEvent.h>
-static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
-{
- int t;
- u32 * inUseP = &(lpQueue->xInUseWord);
-
- __asm__ __volatile__("\n\
-1: lwarx %0,0,%2 \n\
- cmpwi 0,%0,0 \n\
- li %0,0 \n\
- bne- 2f \n\
- addi %0,%0,1 \n\
- stwcx. %0,0,%2 \n\
- bne- 1b \n\
-2: eieio"
- : "=&r" (t), "=m" (lpQueue->xInUseWord)
- : "r" (inUseP), "m" (lpQueue->xInUseWord)
- : "cc");
-
- return t;
-}
+/*
+ * The LpQueue is used to pass event data from the hypervisor to
+ * the partition. This is where I/O interrupt events are communicated.
+ *
+ * It is written to by the hypervisor so cannot end up in the BSS.
+ */
+struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data")));
-static __inline__ void clear_inUse( struct ItLpQueue * lpQueue )
-{
- lpQueue->xInUseWord = 0;
-}
+DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts);
+
+static char *event_types[HvLpEvent_Type_NumTypes] = {
+ "Hypervisor",
+ "Machine Facilities",
+ "Session Manager",
+ "SPD I/O",
+ "Virtual Bus",
+ "PCI I/O",
+ "RIO I/O",
+ "Virtual Lan",
+ "Virtual I/O"
+};
/* Array of LpEvent handler functions */
extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
-unsigned long ItLpQueueInProcess = 0;
-struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue )
+static struct HvLpEvent * get_next_hvlpevent(void)
{
- struct HvLpEvent * nextLpEvent =
- (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;
- if ( nextLpEvent->xFlags.xValid ) {
+ struct HvLpEvent * event;
+ event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
+
+ if (event->xFlags.xValid) {
/* rmb() needed only for weakly consistent machines (regatta) */
rmb();
/* Set pointer to next potential event */
- lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +
- LpEventAlign ) /
- LpEventAlign ) *
- LpEventAlign;
+ hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 +
+ LpEventAlign) / LpEventAlign) * LpEventAlign;
+
/* Wrap to beginning if no room at end */
- if (lpQueue->xSlicCurEventPtr > lpQueue->xSlicLastValidEventPtr)
- lpQueue->xSlicCurEventPtr = lpQueue->xSlicEventStackPtr;
+ if (hvlpevent_queue.xSlicCurEventPtr >
+ hvlpevent_queue.xSlicLastValidEventPtr) {
+ hvlpevent_queue.xSlicCurEventPtr =
+ hvlpevent_queue.xSlicEventStackPtr;
+ }
+ } else {
+ event = NULL;
}
- else
- nextLpEvent = NULL;
- return nextLpEvent;
+ return event;
}
-int ItLpQueue_isLpIntPending( struct ItLpQueue * lpQueue )
+static unsigned long spread_lpevents = NR_CPUS;
+
+int hvlpevent_is_pending(void)
{
- int retval = 0;
- struct HvLpEvent * nextLpEvent;
- if ( lpQueue ) {
- nextLpEvent = (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;
- retval = nextLpEvent->xFlags.xValid | lpQueue->xPlicOverflowIntPending;
- }
- return retval;
+ struct HvLpEvent *next_event;
+
+ if (smp_processor_id() >= spread_lpevents)
+ return 0;
+
+ next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
+
+ return next_event->xFlags.xValid |
+ hvlpevent_queue.xPlicOverflowIntPending;
}
-void ItLpQueue_clearValid( struct HvLpEvent * event )
+static void hvlpevent_clear_valid(struct HvLpEvent * event)
{
- /* Clear the valid bit of the event
- * Also clear bits within this event that might
- * look like valid bits (on 64-byte boundaries)
- */
- unsigned extra = (( event->xSizeMinus1 + LpEventAlign ) /
- LpEventAlign ) - 1;
- switch ( extra ) {
- case 3:
- ((struct HvLpEvent*)((char*)event+3*LpEventAlign))->xFlags.xValid=0;
- case 2:
- ((struct HvLpEvent*)((char*)event+2*LpEventAlign))->xFlags.xValid=0;
- case 1:
- ((struct HvLpEvent*)((char*)event+1*LpEventAlign))->xFlags.xValid=0;
- case 0:
- ;
+ /* Tell the Hypervisor that we're done with this event.
+ * Also clear bits within this event that might look like valid bits.
+ * ie. on 64-byte boundaries.
+ */
+ struct HvLpEvent *tmp;
+ unsigned extra = ((event->xSizeMinus1 + LpEventAlign) /
+ LpEventAlign) - 1;
+
+ switch (extra) {
+ case 3:
+ tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
+ tmp->xFlags.xValid = 0;
+ case 2:
+ tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
+ tmp->xFlags.xValid = 0;
+ case 1:
+ tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
+ tmp->xFlags.xValid = 0;
}
+
mb();
+
event->xFlags.xValid = 0;
}
-unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs )
+void process_hvlpevents(struct pt_regs *regs)
{
- unsigned numIntsProcessed = 0;
- struct HvLpEvent * nextLpEvent;
+ struct HvLpEvent * event;
/* If we have recursed, just return */
- if ( !set_inUse( lpQueue ) )
- return 0;
-
- if (ItLpQueueInProcess == 0)
- ItLpQueueInProcess = 1;
- else
- BUG();
+ if (!spin_trylock(&hvlpevent_queue.lock))
+ return;
for (;;) {
- nextLpEvent = ItLpQueue_getNextLpEvent( lpQueue );
- if ( nextLpEvent ) {
- /* Count events to return to caller
- * and count processed events in lpQueue
- */
- ++numIntsProcessed;
- lpQueue->xLpIntCount++;
- /* Call appropriate handler here, passing
+ event = get_next_hvlpevent();
+ if (event) {
+ /* Call appropriate handler here, passing
* a pointer to the LpEvent. The handler
* must make a copy of the LpEvent if it
* needs it in a bottom half. (perhaps for
* an ACK)
- *
- * Handlers are responsible for ACK processing
+ *
+ * Handlers are responsible for ACK processing
*
* The Hypervisor guarantees that LpEvents will
* only be delivered with types that we have
* registered for, so no type check is necessary
* here!
- */
- if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes )
- lpQueue->xLpIntCountByType[nextLpEvent->xType]++;
- if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes &&
- lpEventHandler[nextLpEvent->xType] )
- lpEventHandler[nextLpEvent->xType](nextLpEvent, regs);
+ */
+ if (event->xType < HvLpEvent_Type_NumTypes)
+ __get_cpu_var(hvlpevent_counts)[event->xType]++;
+ if (event->xType < HvLpEvent_Type_NumTypes &&
+ lpEventHandler[event->xType])
+ lpEventHandler[event->xType](event, regs);
else
- printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType );
-
- ItLpQueue_clearValid( nextLpEvent );
- } else if ( lpQueue->xPlicOverflowIntPending )
+ printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
+
+ hvlpevent_clear_valid(event);
+ } else if (hvlpevent_queue.xPlicOverflowIntPending)
/*
* No more valid events. If overflow events are
* pending process them
*/
- HvCallEvent_getOverflowLpEvents( lpQueue->xIndex);
+ HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex);
else
break;
}
- ItLpQueueInProcess = 0;
- mb();
- clear_inUse( lpQueue );
+ spin_unlock(&hvlpevent_queue.lock);
+}
+
+static int set_spread_lpevents(char *str)
+{
+ unsigned long val = simple_strtoul(str, NULL, 0);
+
+ /*
+ * The parameter is the number of processors to share in processing
+ * lp events.
+ */
+ if (( val > 0) && (val <= NR_CPUS)) {
+ spread_lpevents = val;
+ printk("lpevent processing spread over %ld processors\n", val);
+ } else {
+ printk("invalid spread_lpevents %ld\n", val);
+ }
- get_paca()->lpevent_count += numIntsProcessed;
+ return 1;
+}
+__setup("spread_lpevents=", set_spread_lpevents);
+
+void setup_hvlpevent_queue(void)
+{
+ void *eventStack;
+
+ /*
+ * Allocate a page for the Event Stack. The Hypervisor needs the
+ * absolute real address, so we subtract out the KERNELBASE and add
+ * in the absolute real address of the kernel load area.
+ */
+ eventStack = alloc_bootmem_pages(LpEventStackSize);
+ memset(eventStack, 0, LpEventStackSize);
+
+ /* Invoke the hypervisor to initialize the event stack */
+ HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);
+
+ hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack;
+ hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack;
+ hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack +
+ (LpEventStackSize - LpEventMaxSize);
+ hvlpevent_queue.xIndex = 0;
+}
+
+static int proc_lpevents_show(struct seq_file *m, void *v)
+{
+ int cpu, i;
+ unsigned long sum;
+ static unsigned long cpu_totals[NR_CPUS];
+
+ /* FIXME: do we care that there's no locking here? */
+ sum = 0;
+ for_each_online_cpu(cpu) {
+ cpu_totals[cpu] = 0;
+ for (i = 0; i < HvLpEvent_Type_NumTypes; i++) {
+ cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i];
+ }
+ sum += cpu_totals[cpu];
+ }
+
+ seq_printf(m, "LpEventQueue 0\n");
+ seq_printf(m, " events processed:\t%lu\n", sum);
+
+ for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) {
+ sum = 0;
+ for_each_online_cpu(cpu) {
+ sum += per_cpu(hvlpevent_counts, cpu)[i];
+ }
+
+ seq_printf(m, " %-20s %10lu\n", event_types[i], sum);
+ }
+
+ seq_printf(m, "\n events processed by processor:\n");
+
+ for_each_online_cpu(cpu) {
+ seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]);
+ }
+
+ return 0;
+}
+
+static int proc_lpevents_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_lpevents_show, NULL);
+}
- return numIntsProcessed;
+static struct file_operations proc_lpevents_operations = {
+ .open = proc_lpevents_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init proc_lpevents_init(void)
+{
+ struct proc_dir_entry *e;
+
+ e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
+ if (e)
+ e->proc_fops = &proc_lpevents_operations;
+
+ return 0;
}
+__initcall(proc_lpevents_init);
+
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index badc5a44361..6ffcf67dd50 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -28,13 +28,6 @@
#include <asm/iSeries/IoHriProcessorVpd.h>
#include <asm/iSeries/ItSpCommArea.h>
-/* The LpQueue is used to pass event data from the hypervisor to
- * the partition. This is where I/O interrupt events are communicated.
- */
-
-/* May be filled in by the hypervisor so cannot end up in the BSS */
-struct ItLpQueue xItLpQueue __attribute__((__section__(".data")));
-
/* The HvReleaseData is the root of the information shared between
* the hypervisor and Linux.
@@ -200,7 +193,7 @@ struct ItVpdAreas itVpdAreas = {
0,0,0, /* 13 - 15 */
sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
0,0,0,0,0,0, /* 17 - 22 */
- sizeof(struct ItLpQueue),/* 23 length of Lp Queue */
+ sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */
0,0 /* 24 - 25 */
},
.xSlicVpdAdrs = { /* VPD addresses */
@@ -218,7 +211,7 @@ struct ItVpdAreas itVpdAreas = {
0,0,0, /* 13 - 15 */
&xIoHriProcessorVpd, /* 16 Proc Vpd */
0,0,0,0,0,0, /* 17 - 22 */
- &xItLpQueue, /* 23 Lp Queue */
+ &hvlpevent_queue, /* 23 Lp Queue */
0,0
}
};
diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S
index 42fc08cf87a..0482c063c26 100644
--- a/arch/ppc64/kernel/cpu_setup_power4.S
+++ b/arch/ppc64/kernel/cpu_setup_power4.S
@@ -31,10 +31,13 @@ _GLOBAL(__970_cpu_preinit)
*/
mfspr r0,SPRN_PVR
srwi r0,r0,16
- cmpwi cr0,r0,0x39
- cmpwi cr1,r0,0x3c
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ cmpwi r0,0x39
+ beq 1f
+ cmpwi r0,0x3c
+ beq 1f
+ cmpwi r0,0x44
bnelr
+1:
/* Make sure HID4:rm_ci is off before MMU is turned off, that large
* pages are enabled with HID4:61 and clear HID5:DCBZ_size and
@@ -133,12 +136,14 @@ _GLOBAL(__save_cpu_setup)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
srwi r0,r0,16
- cmpwi cr0,r0,0x39
- cmpwi cr1,r0,0x3c
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bne 1f
-
- /* Save HID0,1,4 and 5 */
+ cmpwi r0,0x39
+ beq 1f
+ cmpwi r0,0x3c
+ beq 1f
+ cmpwi r0,0x44
+ bne 2f
+
+1: /* Save HID0,1,4 and 5 */
mfspr r3,SPRN_HID0
std r3,CS_HID0(r5)
mfspr r3,SPRN_HID1
@@ -148,7 +153,7 @@ _GLOBAL(__save_cpu_setup)
mfspr r3,SPRN_HID5
std r3,CS_HID5(r5)
-1:
+2:
mtcr r7
blr
@@ -165,12 +170,14 @@ _GLOBAL(__restore_cpu_setup)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
srwi r0,r0,16
- cmpwi cr0,r0,0x39
- cmpwi cr1,r0,0x3c
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bne 1f
+ cmpwi r0,0x39
+ beq 1f
+ cmpwi r0,0x3c
+ beq 1f
+ cmpwi r0,0x44
+ bnelr
- /* Before accessing memory, we make sure rm_ci is clear */
+1: /* Before accessing memory, we make sure rm_ci is clear */
li r0,0
mfspr r3,SPRN_HID4
rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */
@@ -223,6 +230,5 @@ _GLOBAL(__restore_cpu_setup)
mtspr SPRN_HID5,r3
sync
isync
-1:
blr
diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 1d162c7c59d..77cec42f952 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -49,160 +49,234 @@ extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
#endif
struct cpu_spec cpu_specs[] = {
- { /* Power3 */
- 0xffff0000, 0x00400000, "POWER3 (630)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_IABR | CPU_FTR_PMC8,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power3,
- COMMON_PPC64_FW
- },
- { /* Power3+ */
- 0xffff0000, 0x00410000, "POWER3 (630+)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_IABR | CPU_FTR_PMC8,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power3,
- COMMON_PPC64_FW
- },
- { /* Northstar */
- 0xffff0000, 0x00330000, "RS64-II (northstar)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power3,
- COMMON_PPC64_FW
- },
- { /* Pulsar */
- 0xffff0000, 0x00340000, "RS64-III (pulsar)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power3,
- COMMON_PPC64_FW
- },
- { /* I-star */
- 0xffff0000, 0x00360000, "RS64-III (icestar)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power3,
- COMMON_PPC64_FW
- },
- { /* S-star */
- 0xffff0000, 0x00370000, "RS64-IV (sstar)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power3,
- COMMON_PPC64_FW
- },
- { /* Power4 */
- 0xffff0000, 0x00350000, "POWER4 (gp)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power4,
- COMMON_PPC64_FW
- },
- { /* Power4+ */
- 0xffff0000, 0x00380000, "POWER4+ (gq)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power4,
- COMMON_PPC64_FW
- },
- { /* PPC970 */
- 0xffff0000, 0x00390000, "PPC970",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
- 128, 128,
- __setup_cpu_ppc970,
- COMMON_PPC64_FW
- },
- { /* PPC970FX */
- 0xffff0000, 0x003c0000, "PPC970FX",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
- COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
- 128, 128,
- __setup_cpu_ppc970,
- COMMON_PPC64_FW
- },
- { /* Power5 */
- 0xffff0000, 0x003a0000, "POWER5 (gr)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
- CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
- CPU_FTR_MMCRA_SIHV,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power4,
- COMMON_PPC64_FW
- },
- { /* Power5 */
- 0xffff0000, 0x003b0000, "POWER5 (gs)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
- CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
- CPU_FTR_MMCRA_SIHV,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power4,
- COMMON_PPC64_FW
- },
- { /* BE DD1.x */
- 0xffff0000, 0x00700000, "Broadband Engine",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_SMT,
- COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
- 128, 128,
- __setup_cpu_be,
- COMMON_PPC64_FW
- },
- { /* default match */
- 0x00000000, 0x00000000, "POWER4 (compatible)",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2,
- COMMON_USER_PPC64,
- 128, 128,
- __setup_cpu_power4,
- COMMON_PPC64_FW
- }
+ { /* Power3 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00400000,
+ .cpu_name = "POWER3 (630)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+ CPU_FTR_PMC8,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power3,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Power3+ */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00410000,
+ .cpu_name = "POWER3 (630+)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+ CPU_FTR_PMC8,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power3,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Northstar */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00330000,
+ .cpu_name = "RS64-II (northstar)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+ CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power3,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Pulsar */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00340000,
+ .cpu_name = "RS64-III (pulsar)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+ CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power3,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* I-star */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00360000,
+ .cpu_name = "RS64-III (icestar)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+ CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power3,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* S-star */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00370000,
+ .cpu_name = "RS64-IV (sstar)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+ CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power3,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Power4 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00350000,
+ .cpu_name = "POWER4 (gp)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power4,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Power4+ */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00380000,
+ .cpu_name = "POWER4+ (gq)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power4,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* PPC970 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00390000,
+ .cpu_name = "PPC970",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ .cpu_user_features = COMMON_USER_PPC64 |
+ PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_ppc970,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* PPC970FX */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003c0000,
+ .cpu_name = "PPC970FX",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ .cpu_user_features = COMMON_USER_PPC64 |
+ PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_ppc970,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* PPC970MP */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00440000,
+ .cpu_name = "PPC970MP",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ .cpu_user_features = COMMON_USER_PPC64 |
+ PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_ppc970,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Power5 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003a0000,
+ .cpu_name = "POWER5 (gr)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
+ CPU_FTR_MMCRA_SIHV,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power4,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* Power5 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003b0000,
+ .cpu_name = "POWER5 (gs)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
+ CPU_FTR_MMCRA_SIHV,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power4,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* BE DD1.x */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00700000,
+ .cpu_name = "Broadband Engine",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_SMT,
+ .cpu_user_features = COMMON_USER_PPC64 |
+ PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_be,
+ .firmware_features = COMMON_PPC64_FW,
+ },
+ { /* default match */
+ .pvr_mask = 0x00000000,
+ .pvr_value = 0x00000000,
+ .cpu_name = "POWER4 (compatible)",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2,
+ .cpu_user_features = COMMON_USER_PPC64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power4,
+ .firmware_features = COMMON_PPC64_FW,
+ }
};
firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
- {FW_FEATURE_PFT, "hcall-pft"},
- {FW_FEATURE_TCE, "hcall-tce"},
- {FW_FEATURE_SPRG0, "hcall-sprg0"},
- {FW_FEATURE_DABR, "hcall-dabr"},
- {FW_FEATURE_COPY, "hcall-copy"},
- {FW_FEATURE_ASR, "hcall-asr"},
- {FW_FEATURE_DEBUG, "hcall-debug"},
- {FW_FEATURE_PERF, "hcall-perf"},
- {FW_FEATURE_DUMP, "hcall-dump"},
- {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
- {FW_FEATURE_MIGRATE, "hcall-migrate"},
- {FW_FEATURE_PERFMON, "hcall-perfmon"},
- {FW_FEATURE_CRQ, "hcall-crq"},
- {FW_FEATURE_VIO, "hcall-vio"},
- {FW_FEATURE_RDMA, "hcall-rdma"},
- {FW_FEATURE_LLAN, "hcall-lLAN"},
- {FW_FEATURE_BULK, "hcall-bulk"},
- {FW_FEATURE_XDABR, "hcall-xdabr"},
- {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
- {FW_FEATURE_SPLPAR, "hcall-splpar"},
+ {FW_FEATURE_PFT, "hcall-pft"},
+ {FW_FEATURE_TCE, "hcall-tce"},
+ {FW_FEATURE_SPRG0, "hcall-sprg0"},
+ {FW_FEATURE_DABR, "hcall-dabr"},
+ {FW_FEATURE_COPY, "hcall-copy"},
+ {FW_FEATURE_ASR, "hcall-asr"},
+ {FW_FEATURE_DEBUG, "hcall-debug"},
+ {FW_FEATURE_PERF, "hcall-perf"},
+ {FW_FEATURE_DUMP, "hcall-dump"},
+ {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
+ {FW_FEATURE_MIGRATE, "hcall-migrate"},
+ {FW_FEATURE_PERFMON, "hcall-perfmon"},
+ {FW_FEATURE_CRQ, "hcall-crq"},
+ {FW_FEATURE_VIO, "hcall-vio"},
+ {FW_FEATURE_RDMA, "hcall-rdma"},
+ {FW_FEATURE_LLAN, "hcall-lLAN"},
+ {FW_FEATURE_BULK, "hcall-bulk"},
+ {FW_FEATURE_XDABR, "hcall-xdabr"},
+ {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
+ {FW_FEATURE_SPLPAR, "hcall-splpar"},
};
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 675c2708588..93ebcac0d5a 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -308,6 +308,7 @@ exception_marker:
label##_pSeries: \
HMT_MEDIUM; \
mtspr SPRG1,r13; /* save r13 */ \
+ RUNLATCH_ON(r13); \
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
#define STD_EXCEPTION_ISERIES(n, label, area) \
@@ -315,6 +316,7 @@ label##_pSeries: \
label##_iSeries: \
HMT_MEDIUM; \
mtspr SPRG1,r13; /* save r13 */ \
+ RUNLATCH_ON(r13); \
EXCEPTION_PROLOG_ISERIES_1(area); \
EXCEPTION_PROLOG_ISERIES_2; \
b label##_common
@@ -324,6 +326,7 @@ label##_iSeries: \
label##_iSeries: \
HMT_MEDIUM; \
mtspr SPRG1,r13; /* save r13 */ \
+ RUNLATCH_ON(r13); \
EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
lbz r10,PACAPROCENABLED(r13); \
cmpwi 0,r10,0; \
@@ -393,6 +396,7 @@ __start_interrupts:
_machine_check_pSeries:
HMT_MEDIUM
mtspr SPRG1,r13 /* save r13 */
+ RUNLATCH_ON(r13)
EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
. = 0x300
@@ -419,6 +423,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
data_access_slb_pSeries:
HMT_MEDIUM
mtspr SPRG1,r13
+ RUNLATCH_ON(r13)
mfspr r13,SPRG3 /* get paca address into r13 */
std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
std r10,PACA_EXSLB+EX_R10(r13)
@@ -439,6 +444,7 @@ data_access_slb_pSeries:
instruction_access_slb_pSeries:
HMT_MEDIUM
mtspr SPRG1,r13
+ RUNLATCH_ON(r13)
mfspr r13,SPRG3 /* get paca address into r13 */
std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
std r10,PACA_EXSLB+EX_R10(r13)
@@ -464,6 +470,7 @@ instruction_access_slb_pSeries:
.globl system_call_pSeries
system_call_pSeries:
HMT_MEDIUM
+ RUNLATCH_ON(r9)
mr r9,r13
mfmsr r10
mfspr r13,SPRG3
@@ -707,11 +714,13 @@ fwnmi_data_area:
system_reset_fwnmi:
HMT_MEDIUM
mtspr SPRG1,r13 /* save r13 */
+ RUNLATCH_ON(r13)
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi
machine_check_fwnmi:
HMT_MEDIUM
mtspr SPRG1,r13 /* save r13 */
+ RUNLATCH_ON(r13)
EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
/*
@@ -848,6 +857,7 @@ unrecov_fer:
.align 7
.globl data_access_common
data_access_common:
+ RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */
mfspr r10,DAR
std r10,PACA_EXGEN+EX_DAR(r13)
mfspr r10,DSISR
diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c
index c72fb8ffe97..138e128a388 100644
--- a/arch/ppc64/kernel/hvconsole.c
+++ b/arch/ppc64/kernel/hvconsole.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <asm/hvcall.h>
#include <asm/hvconsole.h>
-#include <asm/prom.h>
/**
* hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
@@ -42,29 +41,14 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
unsigned long got;
if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
- (unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
- /*
- * Work around a HV bug where it gives us a null
- * after every \r. -- paulus
- */
- if (got > 0) {
- int i;
- for (i = 1; i < got; ++i) {
- if (buf[i] == 0 && buf[i-1] == '\r') {
- --got;
- if (i < got)
- memmove(&buf[i], &buf[i+1],
- got - i);
- }
- }
- }
+ (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
return got;
- }
return 0;
}
EXPORT_SYMBOL(hvc_get_chars);
+
/**
* hvc_put_chars: send characters to firmware for denoted vterm adapter
* @vtermno: The vtermno or unit_address of the adapter from which the data
@@ -88,34 +72,3 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
}
EXPORT_SYMBOL(hvc_put_chars);
-
-/*
- * We hope/assume that the first vty found corresponds to the first console
- * device.
- */
-int hvc_find_vtys(void)
-{
- struct device_node *vty;
- int num_found = 0;
-
- for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
- vty = of_find_node_by_name(vty, "vty")) {
- uint32_t *vtermno;
-
- /* We have statically defined space for only a certain number of
- * console adapters. */
- if (num_found >= MAX_NR_HVC_CONSOLES)
- break;
-
- vtermno = (uint32_t *)get_property(vty, "reg", NULL);
- if (!vtermno)
- continue;
-
- if (device_is_compatible(vty, "hvterm1")) {
- hvc_instantiate(*vtermno, num_found);
- ++num_found;
- }
- }
-
- return num_found;
-}
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index aa9e8fdd1a4..b0250ae4a72 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -38,11 +38,12 @@ static inline void iSeries_hunlock(unsigned long slot)
}
static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
- unsigned long prpn, int secondary,
- unsigned long hpteflags, int bolted, int large)
+ unsigned long prpn, unsigned long vflags,
+ unsigned long rflags)
{
long slot;
- HPTE lhpte;
+ hpte_t lhpte;
+ int secondary = 0;
/*
* The hypervisor tries both primary and secondary.
@@ -50,13 +51,13 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
* it means we have already tried both primary and secondary,
* so we return failure immediately.
*/
- if (secondary)
+ if (vflags & HPTE_V_SECONDARY)
return -1;
iSeries_hlock(hpte_group);
slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
- BUG_ON(lhpte.dw0.dw0.v);
+ BUG_ON(lhpte.v & HPTE_V_VALID);
if (slot == -1) { /* No available entry found in either group */
iSeries_hunlock(hpte_group);
@@ -64,19 +65,13 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
}
if (slot < 0) { /* MSB set means secondary group */
+ vflags |= HPTE_V_VALID;
secondary = 1;
slot &= 0x7fffffffffffffff;
}
- lhpte.dw1.dword1 = 0;
- lhpte.dw1.dw1.rpn = physRpn_to_absRpn(prpn);
- lhpte.dw1.flags.flags = hpteflags;
-
- lhpte.dw0.dword0 = 0;
- lhpte.dw0.dw0.avpn = va >> 23;
- lhpte.dw0.dw0.h = secondary;
- lhpte.dw0.dw0.bolted = bolted;
- lhpte.dw0.dw0.v = 1;
+ lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
+ lhpte.r = (physRpn_to_absRpn(prpn) << HPTE_R_RPN_SHIFT) | rflags;
/* Now fill in the actual HPTE */
HvCallHpt_addValidate(slot, secondary, &lhpte);
@@ -88,20 +83,17 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
static unsigned long iSeries_hpte_getword0(unsigned long slot)
{
- unsigned long dword0;
- HPTE hpte;
+ hpte_t hpte;
HvCallHpt_get(&hpte, slot);
- dword0 = hpte.dw0.dword0;
-
- return dword0;
+ return hpte.v;
}
static long iSeries_hpte_remove(unsigned long hpte_group)
{
unsigned long slot_offset;
int i;
- HPTE lhpte;
+ unsigned long hpte_v;
/* Pick a random slot to start at */
slot_offset = mftb() & 0x7;
@@ -109,10 +101,9 @@ static long iSeries_hpte_remove(unsigned long hpte_group)
iSeries_hlock(hpte_group);
for (i = 0; i < HPTES_PER_GROUP; i++) {
- lhpte.dw0.dword0 =
- iSeries_hpte_getword0(hpte_group + slot_offset);
+ hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset);
- if (!lhpte.dw0.dw0.bolted) {
+ if (! (hpte_v & HPTE_V_BOLTED)) {
HvCallHpt_invalidateSetSwBitsGet(hpte_group +
slot_offset, 0, 0);
iSeries_hunlock(hpte_group);
@@ -137,13 +128,13 @@ static long iSeries_hpte_remove(unsigned long hpte_group)
static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long va, int large, int local)
{
- HPTE hpte;
+ hpte_t hpte;
unsigned long avpn = va >> 23;
iSeries_hlock(slot);
HvCallHpt_get(&hpte, slot);
- if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) {
+ if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) {
/*
* Hypervisor expects bits as NPPP, which is
* different from how they are mapped in our PP.
@@ -167,7 +158,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
*/
static long iSeries_hpte_find(unsigned long vpn)
{
- HPTE hpte;
+ hpte_t hpte;
long slot;
/*
@@ -177,7 +168,7 @@ static long iSeries_hpte_find(unsigned long vpn)
* 0x80000000xxxxxxxx : Entry found in secondary group, slot x
*/
slot = HvCallHpt_findValid(&hpte, vpn);
- if (hpte.dw0.dw0.v) {
+ if (hpte.v & HPTE_V_VALID) {
if (slot < 0) {
slot &= 0x7fffffffffffffff;
slot = -slot;
@@ -212,7 +203,7 @@ static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
int large, int local)
{
- HPTE lhpte;
+ unsigned long hpte_v;
unsigned long avpn = va >> 23;
unsigned long flags;
@@ -220,9 +211,9 @@ static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
iSeries_hlock(slot);
- lhpte.dw0.dword0 = iSeries_hpte_getword0(slot);
+ hpte_v = iSeries_hpte_getword0(slot);
- if ((lhpte.dw0.dw0.avpn == avpn) && lhpte.dw0.dw0.v)
+ if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID))
HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0);
iSeries_hunlock(slot);
diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c
index 356bd9931fc..0fe3116eba2 100644
--- a/arch/ppc64/kernel/iSeries_proc.c
+++ b/arch/ppc64/kernel/iSeries_proc.c
@@ -40,50 +40,6 @@ static int __init iseries_proc_create(void)
}
core_initcall(iseries_proc_create);
-static char *event_types[9] = {
- "Hypervisor\t\t",
- "Machine Facilities\t",
- "Session Manager\t",
- "SPD I/O\t\t",
- "Virtual Bus\t\t",
- "PCI I/O\t\t",
- "RIO I/O\t\t",
- "Virtual Lan\t\t",
- "Virtual I/O\t\t"
-};
-
-static int proc_lpevents_show(struct seq_file *m, void *v)
-{
- unsigned int i;
-
- seq_printf(m, "LpEventQueue 0\n");
- seq_printf(m, " events processed:\t%lu\n",
- (unsigned long)xItLpQueue.xLpIntCount);
-
- for (i = 0; i < 9; ++i)
- seq_printf(m, " %s %10lu\n", event_types[i],
- (unsigned long)xItLpQueue.xLpIntCountByType[i]);
-
- seq_printf(m, "\n events processed by processor:\n");
-
- for_each_online_cpu(i)
- seq_printf(m, " CPU%02d %10u\n", i, paca[i].lpevent_count);
-
- return 0;
-}
-
-static int proc_lpevents_open(struct inode *inode, struct file *file)
-{
- return single_open(file, proc_lpevents_show, NULL);
-}
-
-static struct file_operations proc_lpevents_operations = {
- .open = proc_lpevents_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static unsigned long startTitan = 0;
static unsigned long startTb = 0;
@@ -148,10 +104,6 @@ static int __init iseries_proc_init(void)
{
struct proc_dir_entry *e;
- e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
- if (e)
- e->proc_fops = &proc_lpevents_operations;
-
e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
if (e)
e->proc_fops = &proc_titantod_operations;
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 86966ce76b5..a649edbb23b 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -24,7 +24,6 @@
#include <linux/smp.h>
#include <linux/param.h>
#include <linux/string.h>
-#include <linux/bootmem.h>
#include <linux/initrd.h>
#include <linux/seq_file.h>
#include <linux/kdev_t.h>
@@ -504,7 +503,7 @@ static void __init build_iSeries_Memory_Map(void)
/* Fill in the hashed page table hash mask */
num_ptegs = hptSizePages *
- (PAGE_SIZE / (sizeof(HPTE) * HPTES_PER_GROUP));
+ (PAGE_SIZE / (sizeof(hpte_t) * HPTES_PER_GROUP));
htab_hash_mask = num_ptegs - 1;
/*
@@ -619,25 +618,23 @@ static void __init setup_iSeries_cache_sizes(void)
static void iSeries_make_pte(unsigned long va, unsigned long pa,
int mode)
{
- HPTE local_hpte, rhpte;
+ hpte_t local_hpte, rhpte;
unsigned long hash, vpn;
long slot;
vpn = va >> PAGE_SHIFT;
hash = hpt_hash(vpn, 0);
- local_hpte.dw1.dword1 = pa | mode;
- local_hpte.dw0.dword0 = 0;
- local_hpte.dw0.dw0.avpn = va >> 23;
- local_hpte.dw0.dw0.bolted = 1; /* bolted */
- local_hpte.dw0.dw0.v = 1;
+ local_hpte.r = pa | mode;
+ local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
+ | HPTE_V_BOLTED | HPTE_V_VALID;
slot = HvCallHpt_findValid(&rhpte, vpn);
if (slot < 0) {
/* Must find space in primary group */
panic("hash_page: hpte already exists\n");
}
- HvCallHpt_addValidate(slot, 0, (HPTE *)&local_hpte );
+ HvCallHpt_addValidate(slot, 0, &local_hpte);
}
/*
@@ -647,7 +644,7 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
{
unsigned long pa;
unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
- HPTE hpte;
+ hpte_t hpte;
for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
unsigned long ea = (unsigned long)__va(pa);
@@ -660,7 +657,7 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
if (!in_kernel_text(ea))
mode_rw |= HW_NO_EXEC;
- if (hpte.dw0.dw0.v) {
+ if (hpte.v & HPTE_V_VALID) {
/* HPTE exists, so just bolt it */
HvCallHpt_setSwBits(slot, 0x10, 0);
/* And make sure the pp bits are correct */
@@ -676,7 +673,6 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
*/
static void __init iSeries_setup_arch(void)
{
- void *eventStack;
unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
/* Add an eye catcher and the systemcfg layout version number */
@@ -685,24 +681,7 @@ static void __init iSeries_setup_arch(void)
systemcfg->version.minor = SYSTEMCFG_MINOR;
/* Setup the Lp Event Queue */
-
- /* Allocate a page for the Event Stack
- * The hypervisor wants the absolute real address, so
- * we subtract out the KERNELBASE and add in the
- * absolute real address of the kernel load area
- */
- eventStack = alloc_bootmem_pages(LpEventStackSize);
- memset(eventStack, 0, LpEventStackSize);
-
- /* Invoke the hypervisor to initialize the event stack */
- HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);
-
- /* Initialize fields in our Lp Event Queue */
- xItLpQueue.xSlicEventStackPtr = (char *)eventStack;
- xItLpQueue.xSlicCurEventPtr = (char *)eventStack;
- xItLpQueue.xSlicLastValidEventPtr = (char *)eventStack +
- (LpEventStackSize - LpEventMaxSize);
- xItLpQueue.xIndex = 0;
+ setup_hvlpevent_queue();
/* Compute processor frequency */
procFreqHz = ((1UL << 34) * 1000000) /
@@ -853,27 +832,91 @@ static int __init iSeries_src_init(void)
late_initcall(iSeries_src_init);
-static int set_spread_lpevents(char *str)
+static inline void process_iSeries_events(void)
{
- unsigned long i;
- unsigned long val = simple_strtoul(str, NULL, 0);
+ asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
+}
+
+static void yield_shared_processor(void)
+{
+ unsigned long tb;
+
+ HvCall_setEnabledInterrupts(HvCall_MaskIPI |
+ HvCall_MaskLpEvent |
+ HvCall_MaskLpProd |
+ HvCall_MaskTimeout);
+
+ tb = get_tb();
+ /* Compute future tb value when yield should expire */
+ HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
/*
- * The parameter is the number of processors to share in processing
- * lp events.
+ * The decrementer stops during the yield. Force a fake decrementer
+ * here and let the timer_interrupt code sort out the actual time.
*/
- if (( val > 0) && (val <= NR_CPUS)) {
- for (i = 1; i < val; ++i)
- paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
+ get_paca()->lppaca.int_dword.fields.decr_int = 1;
+ process_iSeries_events();
+}
- printk("lpevent processing spread over %ld processors\n", val);
- } else {
- printk("invalid spread_lpevents %ld\n", val);
+static int iseries_shared_idle(void)
+{
+ while (1) {
+ while (!need_resched() && !hvlpevent_is_pending()) {
+ local_irq_disable();
+ ppc64_runlatch_off();
+
+ /* Recheck with irqs off */
+ if (!need_resched() && !hvlpevent_is_pending())
+ yield_shared_processor();
+
+ HMT_medium();
+ local_irq_enable();
+ }
+
+ ppc64_runlatch_on();
+
+ if (hvlpevent_is_pending())
+ process_iSeries_events();
+
+ schedule();
+ }
+
+ return 0;
+}
+
+static int iseries_dedicated_idle(void)
+{
+ long oldval;
+
+ while (1) {
+ oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+
+ if (!oldval) {
+ set_thread_flag(TIF_POLLING_NRFLAG);
+
+ while (!need_resched()) {
+ ppc64_runlatch_off();
+ HMT_low();
+
+ if (hvlpevent_is_pending()) {
+ HMT_medium();
+ ppc64_runlatch_on();
+ process_iSeries_events();
+ }
+ }
+
+ HMT_medium();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ } else {
+ set_need_resched();
+ }
+
+ ppc64_runlatch_on();
+ schedule();
}
- return 1;
+ return 0;
}
-__setup("spread_lpevents=", set_spread_lpevents);
#ifndef CONFIG_PCI
void __init iSeries_init_IRQ(void) { }
@@ -900,5 +943,13 @@ void __init iSeries_early_setup(void)
ppc_md.get_rtc_time = iSeries_get_rtc_time;
ppc_md.calibrate_decr = iSeries_calibrate_decr;
ppc_md.progress = iSeries_progress;
+
+ if (get_paca()->lppaca.shared_proc) {
+ ppc_md.idle_loop = iseries_shared_idle;
+ printk(KERN_INFO "Using shared processor idle loop\n");
+ } else {
+ ppc_md.idle_loop = iseries_dedicated_idle;
+ printk(KERN_INFO "Using dedicated idle loop\n");
+ }
}
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index bdf13b4dc1c..954395d4263 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -20,109 +20,18 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/cpu.h>
-#include <linux/module.h>
#include <linux/sysctl.h>
-#include <linux/smp.h>
#include <asm/system.h>
#include <asm/processor.h>
-#include <asm/mmu.h>
#include <asm/cputable.h>
#include <asm/time.h>
-#include <asm/iSeries/HvCall.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/plpar_wrappers.h>
#include <asm/systemcfg.h>
+#include <asm/machdep.h>
extern void power4_idle(void);
-static int (*idle_loop)(void);
-
-#ifdef CONFIG_PPC_ISERIES
-static unsigned long maxYieldTime = 0;
-static unsigned long minYieldTime = 0xffffffffffffffffUL;
-
-static inline void process_iSeries_events(void)
-{
- asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
-}
-
-static void yield_shared_processor(void)
-{
- unsigned long tb;
- unsigned long yieldTime;
-
- HvCall_setEnabledInterrupts(HvCall_MaskIPI |
- HvCall_MaskLpEvent |
- HvCall_MaskLpProd |
- HvCall_MaskTimeout);
-
- tb = get_tb();
- /* Compute future tb value when yield should expire */
- HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
-
- yieldTime = get_tb() - tb;
- if (yieldTime > maxYieldTime)
- maxYieldTime = yieldTime;
-
- if (yieldTime < minYieldTime)
- minYieldTime = yieldTime;
-
- /*
- * The decrementer stops during the yield. Force a fake decrementer
- * here and let the timer_interrupt code sort out the actual time.
- */
- get_paca()->lppaca.int_dword.fields.decr_int = 1;
- process_iSeries_events();
-}
-
-static int iSeries_idle(void)
-{
- struct paca_struct *lpaca;
- long oldval;
-
- /* ensure iSeries run light will be out when idle */
- ppc64_runlatch_off();
-
- lpaca = get_paca();
-
- while (1) {
- if (lpaca->lppaca.shared_proc) {
- if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr))
- process_iSeries_events();
- if (!need_resched())
- yield_shared_processor();
- } else {
- oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-
- if (!oldval) {
- set_thread_flag(TIF_POLLING_NRFLAG);
-
- while (!need_resched()) {
- HMT_medium();
- if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr))
- process_iSeries_events();
- HMT_low();
- }
-
- HMT_medium();
- clear_thread_flag(TIF_POLLING_NRFLAG);
- } else {
- set_need_resched();
- }
- }
-
- ppc64_runlatch_on();
- schedule();
- ppc64_runlatch_off();
- }
-
- return 0;
-}
-
-#else
-
-static int default_idle(void)
+int default_idle(void)
{
long oldval;
unsigned int cpu = smp_processor_id();
@@ -134,7 +43,8 @@ static int default_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (!need_resched() && !cpu_is_offline(cpu)) {
- barrier();
+ ppc64_runlatch_off();
+
/*
* Go into low thread priority and possibly
* low power mode.
@@ -149,6 +59,7 @@ static int default_idle(void)
set_need_resched();
}
+ ppc64_runlatch_on();
schedule();
if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
cpu_die();
@@ -157,127 +68,19 @@ static int default_idle(void)
return 0;
}
-#ifdef CONFIG_PPC_PSERIES
-
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-
-int dedicated_idle(void)
+int native_idle(void)
{
- long oldval;
- struct paca_struct *lpaca = get_paca(), *ppaca;
- unsigned long start_snooze;
- unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
- unsigned int cpu = smp_processor_id();
-
- ppaca = &paca[cpu ^ 1];
-
while (1) {
- /*
- * Indicate to the HV that we are idle. Now would be
- * a good time to find other work to dispatch.
- */
- lpaca->lppaca.idle = 1;
-
- oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
- if (!oldval) {
- set_thread_flag(TIF_POLLING_NRFLAG);
- start_snooze = __get_tb() +
- *smt_snooze_delay * tb_ticks_per_usec;
- while (!need_resched() && !cpu_is_offline(cpu)) {
- /*
- * Go into low thread priority and possibly
- * low power mode.
- */
- HMT_low();
- HMT_very_low();
-
- if (*smt_snooze_delay == 0 ||
- __get_tb() < start_snooze)
- continue;
-
- HMT_medium();
-
- if (!(ppaca->lppaca.idle)) {
- local_irq_disable();
-
- /*
- * We are about to sleep the thread
- * and so wont be polling any
- * more.
- */
- clear_thread_flag(TIF_POLLING_NRFLAG);
-
- /*
- * SMT dynamic mode. Cede will result
- * in this thread going dormant, if the
- * partner thread is still doing work.
- * Thread wakes up if partner goes idle,
- * an interrupt is presented, or a prod
- * occurs. Returning from the cede
- * enables external interrupts.
- */
- if (!need_resched())
- cede_processor();
- else
- local_irq_enable();
- } else {
- /*
- * Give the HV an opportunity at the
- * processor, since we are not doing
- * any work.
- */
- poll_pending();
- }
- }
-
- clear_thread_flag(TIF_POLLING_NRFLAG);
- } else {
- set_need_resched();
- }
-
- HMT_medium();
- lpaca->lppaca.idle = 0;
- schedule();
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- }
- return 0;
-}
-
-static int shared_idle(void)
-{
- struct paca_struct *lpaca = get_paca();
- unsigned int cpu = smp_processor_id();
-
- while (1) {
- /*
- * Indicate to the HV that we are idle. Now would be
- * a good time to find other work to dispatch.
- */
- lpaca->lppaca.idle = 1;
+ ppc64_runlatch_off();
- while (!need_resched() && !cpu_is_offline(cpu)) {
- local_irq_disable();
+ if (!need_resched())
+ power4_idle();
- /*
- * Yield the processor to the hypervisor. We return if
- * an external interrupt occurs (which are driven prior
- * to returning here) or if a prod occurs from another
- * processor. When returning here, external interrupts
- * are enabled.
- *
- * Check need_resched() again with interrupts disabled
- * to avoid a race.
- */
- if (!need_resched())
- cede_processor();
- else
- local_irq_enable();
+ if (need_resched()) {
+ ppc64_runlatch_on();
+ schedule();
}
- HMT_medium();
- lpaca->lppaca.idle = 0;
- schedule();
if (cpu_is_offline(smp_processor_id()) &&
system_state == SYSTEM_RUNNING)
cpu_die();
@@ -286,29 +89,10 @@ static int shared_idle(void)
return 0;
}
-#endif /* CONFIG_PPC_PSERIES */
-
-static int native_idle(void)
-{
- while(1) {
- /* check CPU type here */
- if (!need_resched())
- power4_idle();
- if (need_resched())
- schedule();
-
- if (cpu_is_offline(raw_smp_processor_id()) &&
- system_state == SYSTEM_RUNNING)
- cpu_die();
- }
- return 0;
-}
-
-#endif /* CONFIG_PPC_ISERIES */
-
void cpu_idle(void)
{
- idle_loop();
+ BUG_ON(NULL == ppc_md.idle_loop);
+ ppc_md.idle_loop();
}
int powersave_nap;
@@ -342,42 +126,3 @@ register_powersave_nap_sysctl(void)
}
__initcall(register_powersave_nap_sysctl);
#endif
-
-int idle_setup(void)
-{
- /*
- * Move that junk to each platform specific file, eventually define
- * a pSeries_idle for shared processor stuff
- */
-#ifdef CONFIG_PPC_ISERIES
- idle_loop = iSeries_idle;
- return 1;
-#else
- idle_loop = default_idle;
-#endif
-#ifdef CONFIG_PPC_PSERIES
- if (systemcfg->platform & PLATFORM_PSERIES) {
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
- if (get_paca()->lppaca.shared_proc) {
- printk(KERN_INFO "Using shared processor idle loop\n");
- idle_loop = shared_idle;
- } else {
- printk(KERN_INFO "Using dedicated idle loop\n");
- idle_loop = dedicated_idle;
- }
- } else {
- printk(KERN_INFO "Using default idle loop\n");
- idle_loop = default_idle;
- }
- }
-#endif /* CONFIG_PPC_PSERIES */
-#ifndef CONFIG_PPC_ISERIES
- if (systemcfg->platform == PLATFORM_POWERMAC ||
- systemcfg->platform == PLATFORM_MAPLE) {
- printk(KERN_INFO "Using native/NAP idle loop\n");
- idle_loop = native_idle;
- }
-#endif /* CONFIG_PPC_ISERIES */
-
- return 1;
-}
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
index 3defc8c33ad..f41afe54504 100644
--- a/arch/ppc64/kernel/irq.c
+++ b/arch/ppc64/kernel/irq.c
@@ -66,7 +66,6 @@ EXPORT_SYMBOL(irq_desc);
int distribute_irqs = 1;
int __irq_offset_value;
int ppc_spurious_interrupts;
-unsigned long lpevent_count;
u64 ppc64_interrupt_controller;
int show_interrupts(struct seq_file *p, void *v)
@@ -245,7 +244,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
spin_lock(&desc->lock);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, regs);
if (likely(!(desc->status & IRQ_PENDING)))
break;
desc->status &= ~IRQ_PENDING;
@@ -269,7 +268,6 @@ out:
void do_IRQ(struct pt_regs *regs)
{
struct paca_struct *lpaca;
- struct ItLpQueue *lpq;
irq_enter();
@@ -295,9 +293,8 @@ void do_IRQ(struct pt_regs *regs)
iSeries_smp_message_recv(regs);
}
#endif /* CONFIG_SMP */
- lpq = lpaca->lpqueue_ptr;
- if (lpq && ItLpQueue_isLpIntPending(lpq))
- lpevent_count += ItLpQueue_process(lpq, regs);
+ if (hvlpevent_is_pending())
+ process_hvlpevents(regs);
irq_exit();
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 782ce3efa2c..a3d519518fb 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -36,6 +36,8 @@
#include <asm/kdebug.h>
#include <asm/sstep.h>
+static DECLARE_MUTEX(kprobe_mutex);
+
static struct kprobe *current_kprobe;
static unsigned long kprobe_status, kprobe_saved_msr;
static struct kprobe *kprobe_prev;
@@ -54,6 +56,15 @@ int arch_prepare_kprobe(struct kprobe *p)
printk("Cannot register a kprobe on rfid or mtmsrd\n");
ret = -EINVAL;
}
+
+ /* insn must be on a special executable page on ppc64 */
+ if (!ret) {
+ up(&kprobe_mutex);
+ p->ainsn.insn = get_insn_slot();
+ down(&kprobe_mutex);
+ if (!p->ainsn.insn)
+ ret = -ENOMEM;
+ }
return ret;
}
@@ -79,16 +90,22 @@ void arch_disarm_kprobe(struct kprobe *p)
void arch_remove_kprobe(struct kprobe *p)
{
+ up(&kprobe_mutex);
+ free_insn_slot(p->ainsn.insn);
+ down(&kprobe_mutex);
}
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
+ kprobe_opcode_t insn = *p->ainsn.insn;
+
regs->msr |= MSR_SE;
- /*single step inline if it a breakpoint instruction*/
- if (p->opcode == BREAKPOINT_INSTRUCTION)
+
+ /* single step inline if it is a trap variant */
+ if (IS_TW(insn) || IS_TD(insn) || IS_TWI(insn) || IS_TDI(insn))
regs->nip = (unsigned long)p->addr;
else
- regs->nip = (unsigned long)&p->ainsn.insn;
+ regs->nip = (unsigned long)p->ainsn.insn;
}
static inline void save_previous_kprobe(void)
@@ -105,6 +122,23 @@ static inline void restore_previous_kprobe(void)
kprobe_saved_msr = kprobe_saved_msr_prev;
}
+void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+{
+ struct kretprobe_instance *ri;
+
+ if ((ri = get_free_rp_inst(rp)) != NULL) {
+ ri->rp = rp;
+ ri->task = current;
+ ri->ret_addr = (kprobe_opcode_t *)regs->link;
+
+ /* Replace the return addr with trampoline addr */
+ regs->link = (unsigned long)kretprobe_trampoline;
+ add_rp_inst(ri);
+ } else {
+ rp->nmissed++;
+ }
+}
+
static inline int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
@@ -195,6 +229,78 @@ no_kprobe:
}
/*
+ * Function return probe trampoline:
+ * - init_kprobes() establishes a probepoint here
+ * - When the probed function returns, this probe
+ * causes the handlers to fire
+ */
+void kretprobe_trampoline_holder(void)
+{
+ asm volatile(".global kretprobe_trampoline\n"
+ "kretprobe_trampoline:\n"
+ "nop\n");
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kretprobe_instance *ri = NULL;
+ struct hlist_head *head;
+ struct hlist_node *node, *tmp;
+ unsigned long orig_ret_address = 0;
+ unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+
+ head = kretprobe_inst_table_head(current);
+
+ /*
+ * It is possible to have multiple instances associated with a given
+ * task either because an multiple functions in the call path
+ * have a return probe installed on them, and/or more then one return
+ * return probe was registered for a target function.
+ *
+ * We can handle this because:
+ * - instances are always inserted at the head of the list
+ * - when multiple return probes are registered for the same
+ * function, the first instance's ret_addr will point to the
+ * real return address, and all the rest will point to
+ * kretprobe_trampoline
+ */
+ hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+ if (ri->task != current)
+ /* another task is sharing our hash bucket */
+ continue;
+
+ if (ri->rp && ri->rp->handler)
+ ri->rp->handler(ri, regs);
+
+ orig_ret_address = (unsigned long)ri->ret_addr;
+ recycle_rp_inst(ri);
+
+ if (orig_ret_address != trampoline_address)
+ /*
+ * This is the real return address. Any other
+ * instances associated with this task are for
+ * other calls deeper on the call stack
+ */
+ break;
+ }
+
+ BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
+ regs->nip = orig_ret_address;
+
+ unlock_kprobes();
+
+ /*
+ * By returning a non-zero value, we are telling
+ * kprobe_handler() that we have handled unlocking
+ * and re-enabling preemption.
+ */
+ return 1;
+}
+
+/*
* Called after single-stepping. p->addr is the address of the
* instruction whose first byte has been replaced by the "breakpoint"
* instruction. To avoid the SMP problems that can occur when we
@@ -205,9 +311,10 @@ no_kprobe:
static void resume_execution(struct kprobe *p, struct pt_regs *regs)
{
int ret;
+ unsigned int insn = *p->ainsn.insn;
regs->nip = (unsigned long)p->addr;
- ret = emulate_step(regs, p->ainsn.insn[0]);
+ ret = emulate_step(regs, insn);
if (ret == 0)
regs->nip = (unsigned long)p->addr + 4;
}
@@ -331,3 +438,13 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
return 1;
}
+
+static struct kprobe trampoline_p = {
+ .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+ .pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
+{
+ return register_kprobe(&trampoline_p);
+}
diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
index da8900b51f4..bb55b5a5691 100644
--- a/arch/ppc64/kernel/maple_setup.c
+++ b/arch/ppc64/kernel/maple_setup.c
@@ -177,6 +177,8 @@ void __init maple_setup_arch(void)
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
+
+ printk(KERN_INFO "Using native/NAP idle loop\n");
}
/*
@@ -297,4 +299,5 @@ struct machdep_calls __initdata maple_md = {
.get_rtc_time = maple_get_rtc_time,
.calibrate_decr = generic_calibrate_decr,
.progress = maple_progress,
+ .idle_loop = native_idle,
};
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
index d98bebf7042..ef4a338ebd0 100644
--- a/arch/ppc64/kernel/mf.c
+++ b/arch/ppc64/kernel/mf.c
@@ -801,10 +801,8 @@ int mf_get_boot_rtc(struct rtc_time *tm)
return rc;
/* We need to poll here as we are not yet taking interrupts */
while (rtc_data.busy) {
- extern unsigned long lpevent_count;
- struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
- if (lpq && ItLpQueue_isLpIntPending(lpq))
- lpevent_count += ItLpQueue_process(lpq, NULL);
+ if (hvlpevent_is_pending())
+ process_hvlpevents(NULL);
}
return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
}
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index f3dea0c5a88..59f4f997381 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -1124,9 +1124,11 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_mq_getsetattr
.llong .compat_sys_kexec_load
.llong .sys32_add_key
- .llong .sys32_request_key
+ .llong .sys32_request_key /* 270 */
.llong .compat_sys_keyctl
.llong .compat_sys_waitid
+ .llong .sys32_ioprio_set
+ .llong .sys32_ioprio_get
.balign 8
_GLOBAL(sys_call_table)
@@ -1403,3 +1405,5 @@ _GLOBAL(sys_call_table)
.llong .sys_request_key /* 270 */
.llong .sys_keyctl
.llong .sys_waitid
+ .llong .sys_ioprio_set
+ .llong .sys_ioprio_get
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
index 4e71781a441..4fb1a9f5060 100644
--- a/arch/ppc64/kernel/nvram.c
+++ b/arch/ppc64/kernel/nvram.c
@@ -338,9 +338,8 @@ static int nvram_remove_os_partition(void)
*/
static int nvram_create_os_partition(void)
{
- struct list_head * p;
- struct nvram_partition *part = NULL;
- struct nvram_partition *new_part = NULL;
+ struct nvram_partition *part;
+ struct nvram_partition *new_part;
struct nvram_partition *free_part = NULL;
int seq_init[2] = { 0, 0 };
loff_t tmp_index;
@@ -349,8 +348,7 @@ static int nvram_create_os_partition(void)
/* Find a free partition that will give us the maximum needed size
If can't find one that will give us the minimum size needed */
- list_for_each(p, &nvram_part->partition) {
- part = list_entry(p, struct nvram_partition, partition);
+ list_for_each_entry(part, &nvram_part->partition, partition) {
if (part->header.signature != NVRAM_SIG_FREE)
continue;
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index 66bd5ab7c25..b80e81984ba 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -3,6 +3,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <asm/errno.h>
#include <asm/of_device.h>
@@ -15,20 +16,20 @@
* Used by a driver to check whether an of_device present in the
* system is in its list of supported devices.
*/
-const struct of_match * of_match_device(const struct of_match *matches,
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct of_device *dev)
{
if (!dev->node)
return NULL;
- while (matches->name || matches->type || matches->compatible) {
+ while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
- if (matches->name && matches->name != OF_ANY_MATCH)
+ if (matches->name[0])
match &= dev->node->name
&& !strcmp(matches->name, dev->node->name);
- if (matches->type && matches->type != OF_ANY_MATCH)
+ if (matches->type[0])
match &= dev->node->type
&& !strcmp(matches->type, dev->node->type);
- if (matches->compatible && matches->compatible != OF_ANY_MATCH)
+ if (matches->compatible[0])
match &= device_is_compatible(dev->node,
matches->compatible);
if (match)
@@ -42,7 +43,7 @@ static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * of_drv = to_of_platform_driver(drv);
- const struct of_match * matches = of_drv->match_table;
+ const struct of_device_id * matches = of_drv->match_table;
if (!matches)
return 0;
@@ -75,7 +76,7 @@ static int of_device_probe(struct device *dev)
int error = -ENODEV;
struct of_platform_driver *drv;
struct of_device *of_dev;
- const struct of_match *match;
+ const struct of_device_id *match;
drv = to_of_platform_driver(dev->driver);
of_dev = to_of_device(dev);
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index 6534812db43..74dd144dcce 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -277,31 +277,20 @@ void vpa_init(int cpu)
long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
- int secondary, unsigned long hpteflags,
- int bolted, int large)
+ unsigned long vflags, unsigned long rflags)
{
unsigned long arpn = physRpn_to_absRpn(prpn);
unsigned long lpar_rc;
unsigned long flags;
unsigned long slot;
- HPTE lhpte;
+ unsigned long hpte_v, hpte_r;
unsigned long dummy0, dummy1;
- /* Fill in the local HPTE with absolute rpn, avpn and flags */
- lhpte.dw1.dword1 = 0;
- lhpte.dw1.dw1.rpn = arpn;
- lhpte.dw1.flags.flags = hpteflags;
+ hpte_v = ((va >> 23) << HPTE_V_AVPN_SHIFT) | vflags | HPTE_V_VALID;
+ if (vflags & HPTE_V_LARGE)
+ hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);
- lhpte.dw0.dword0 = 0;
- lhpte.dw0.dw0.avpn = va >> 23;
- lhpte.dw0.dw0.h = secondary;
- lhpte.dw0.dw0.bolted = bolted;
- lhpte.dw0.dw0.v = 1;
-
- if (large) {
- lhpte.dw0.dw0.l = 1;
- lhpte.dw0.dw0.avpn &= ~0x1UL;
- }
+ hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
/* Now fill in the actual HPTE */
/* Set CEC cookie to 0 */
@@ -312,11 +301,11 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
flags = 0;
/* XXX why is this here? - Anton */
- if (hpteflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
- lhpte.dw1.flags.flags &= ~_PAGE_COHERENT;
+ if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+ hpte_r &= ~_PAGE_COHERENT;
- lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0,
- lhpte.dw1.dword1, &slot, &dummy0, &dummy1);
+ lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
+ hpte_r, &slot, &dummy0, &dummy1);
if (unlikely(lpar_rc == H_PTEG_Full))
return -1;
@@ -332,7 +321,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
/* Because of iSeries, we have to pass down the secondary
* bucket bit here as well
*/
- return (slot & 7) | (secondary << 3);
+ return (slot & 7) | (!!(vflags & HPTE_V_SECONDARY) << 3);
}
static DEFINE_SPINLOCK(pSeries_lpar_tlbie_lock);
@@ -427,22 +416,18 @@ static long pSeries_lpar_hpte_find(unsigned long vpn)
unsigned long hash;
unsigned long i, j;
long slot;
- union {
- unsigned long dword0;
- Hpte_dword0 dw0;
- } hpte_dw0;
- Hpte_dword0 dw0;
+ unsigned long hpte_v;
hash = hpt_hash(vpn, 0);
for (j = 0; j < 2; j++) {
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
for (i = 0; i < HPTES_PER_GROUP; i++) {
- hpte_dw0.dword0 = pSeries_lpar_hpte_getword0(slot);
- dw0 = hpte_dw0.dw0;
+ hpte_v = pSeries_lpar_hpte_getword0(slot);
- if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
- (dw0.h == j)) {
+ if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11))
+ && (hpte_v & HPTE_V_VALID)
+ && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
/* HPTE matches */
if (j)
slot = -slot;
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 44d9af72d22..5bec956e44a 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -19,6 +19,7 @@
#undef DEBUG
#include <linux/config.h>
+#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -82,6 +83,9 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
extern void pSeries_system_reset_exception(struct pt_regs *regs);
extern int pSeries_machine_check_exception(struct pt_regs *regs);
+static int pseries_shared_idle(void);
+static int pseries_dedicated_idle(void);
+
static volatile void __iomem * chrp_int_ack_special;
struct mpic *pSeries_mpic;
@@ -229,6 +233,20 @@ static void __init pSeries_setup_arch(void)
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
vpa_init(boot_cpuid);
+
+ /* Choose an idle loop */
+ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ if (get_paca()->lppaca.shared_proc) {
+ printk(KERN_INFO "Using shared processor idle loop\n");
+ ppc_md.idle_loop = pseries_shared_idle;
+ } else {
+ printk(KERN_INFO "Using dedicated idle loop\n");
+ ppc_md.idle_loop = pseries_dedicated_idle;
+ }
+ } else {
+ printk(KERN_INFO "Using default idle loop\n");
+ ppc_md.idle_loop = default_idle;
+ }
}
static int __init pSeries_init_panel(void)
@@ -418,6 +436,144 @@ static int __init pSeries_probe(int platform)
return 1;
}
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+
+static inline void dedicated_idle_sleep(unsigned int cpu)
+{
+ struct paca_struct *ppaca = &paca[cpu ^ 1];
+
+ /* Only sleep if the other thread is not idle */
+ if (!(ppaca->lppaca.idle)) {
+ local_irq_disable();
+
+ /*
+ * We are about to sleep the thread and so wont be polling any
+ * more.
+ */
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+
+ /*
+ * SMT dynamic mode. Cede will result in this thread going
+ * dormant, if the partner thread is still doing work. Thread
+ * wakes up if partner goes idle, an interrupt is presented, or
+ * a prod occurs. Returning from the cede enables external
+ * interrupts.
+ */
+ if (!need_resched())
+ cede_processor();
+ else
+ local_irq_enable();
+ } else {
+ /*
+ * Give the HV an opportunity at the processor, since we are
+ * not doing any work.
+ */
+ poll_pending();
+ }
+}
+
+static int pseries_dedicated_idle(void)
+{
+ long oldval;
+ struct paca_struct *lpaca = get_paca();
+ unsigned int cpu = smp_processor_id();
+ unsigned long start_snooze;
+ unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
+
+ while (1) {
+ /*
+ * Indicate to the HV that we are idle. Now would be
+ * a good time to find other work to dispatch.
+ */
+ lpaca->lppaca.idle = 1;
+
+ oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+ if (!oldval) {
+ set_thread_flag(TIF_POLLING_NRFLAG);
+
+ start_snooze = __get_tb() +
+ *smt_snooze_delay * tb_ticks_per_usec;
+
+ while (!need_resched() && !cpu_is_offline(cpu)) {
+ ppc64_runlatch_off();
+
+ /*
+ * Go into low thread priority and possibly
+ * low power mode.
+ */
+ HMT_low();
+ HMT_very_low();
+
+ if (*smt_snooze_delay != 0 &&
+ __get_tb() > start_snooze) {
+ HMT_medium();
+ dedicated_idle_sleep(cpu);
+ }
+
+ }
+
+ HMT_medium();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ } else {
+ set_need_resched();
+ }
+
+ lpaca->lppaca.idle = 0;
+ ppc64_runlatch_on();
+
+ schedule();
+
+ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+ cpu_die();
+ }
+}
+
+static int pseries_shared_idle(void)
+{
+ struct paca_struct *lpaca = get_paca();
+ unsigned int cpu = smp_processor_id();
+
+ while (1) {
+ /*
+ * Indicate to the HV that we are idle. Now would be
+ * a good time to find other work to dispatch.
+ */
+ lpaca->lppaca.idle = 1;
+
+ while (!need_resched() && !cpu_is_offline(cpu)) {
+ local_irq_disable();
+ ppc64_runlatch_off();
+
+ /*
+ * Yield the processor to the hypervisor. We return if
+ * an external interrupt occurs (which are driven prior
+ * to returning here) or if a prod occurs from another
+ * processor. When returning here, external interrupts
+ * are enabled.
+ *
+ * Check need_resched() again with interrupts disabled
+ * to avoid a race.
+ */
+ if (!need_resched())
+ cede_processor();
+ else
+ local_irq_enable();
+
+ HMT_medium();
+ }
+
+ lpaca->lppaca.idle = 0;
+ ppc64_runlatch_on();
+
+ schedule();
+
+ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+ cpu_die();
+ }
+
+ return 0;
+}
+
struct machdep_calls __initdata pSeries_md = {
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index a3e0975c26c..6316188737b 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -42,21 +42,7 @@ extern unsigned long __toc_start;
* processors. The processor VPD array needs one entry per physical
* processor (not thread).
*/
-#ifdef CONFIG_PPC_ISERIES
-#define EXTRA_INITS(number, lpq) \
- .lppaca_ptr = &paca[number].lppaca, \
- .lpqueue_ptr = (lpq), /* &xItLpQueue, */ \
- .reg_save_ptr = &paca[number].reg_save, \
- .reg_save = { \
- .xDesc = 0xd397d9e2, /* "LpRS" */ \
- .xSize = sizeof(struct ItLpRegSave) \
- },
-#else
-#define EXTRA_INITS(number, lpq)
-#endif
-
-#define PACAINITDATA(number,start,lpq,asrr,asrv) \
-{ \
+#define PACA_INIT_COMMON(number, start, asrr, asrv) \
.lock_token = 0x8000, \
.paca_index = (number), /* Paca Index */ \
.default_decr = 0x00ff0000, /* Initial Decr */ \
@@ -74,147 +60,79 @@ extern unsigned long __toc_start;
.end_of_quantum = 0xfffffffffffffffful, \
.slb_count = 64, \
}, \
- EXTRA_INITS((number), (lpq)) \
-}
-struct paca_struct paca[] = {
#ifdef CONFIG_PPC_ISERIES
- PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR),
+#define PACA_INIT_ISERIES(number) \
+ .lppaca_ptr = &paca[number].lppaca, \
+ .reg_save_ptr = &paca[number].reg_save, \
+ .reg_save = { \
+ .xDesc = 0xd397d9e2, /* "LpRS" */ \
+ .xSize = sizeof(struct ItLpRegSave) \
+ }
+
+#define PACA_INIT(number) \
+{ \
+ PACA_INIT_COMMON(number, 0, 0, 0) \
+ PACA_INIT_ISERIES(number) \
+}
+
+#define BOOTCPU_PACA_INIT(number) \
+{ \
+ PACA_INIT_COMMON(number, 1, 0, STAB0_VIRT_ADDR) \
+ PACA_INIT_ISERIES(number) \
+}
+
#else
- PACAINITDATA( 0, 1, NULL, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR),
+#define PACA_INIT(number) \
+{ \
+ PACA_INIT_COMMON(number, 0, 0, 0) \
+}
+
+#define BOOTCPU_PACA_INIT(number) \
+{ \
+ PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR) \
+}
#endif
+
+struct paca_struct paca[] = {
+ BOOTCPU_PACA_INIT(0),
#if NR_CPUS > 1
- PACAINITDATA( 1, 0, NULL, 0, 0),
- PACAINITDATA( 2, 0, NULL, 0, 0),
- PACAINITDATA( 3, 0, NULL, 0, 0),
+ PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
#if NR_CPUS > 4
- PACAINITDATA( 4, 0, NULL, 0, 0),
- PACAINITDATA( 5, 0, NULL, 0, 0),
- PACAINITDATA( 6, 0, NULL, 0, 0),
- PACAINITDATA( 7, 0, NULL, 0, 0),
+ PACA_INIT( 4), PACA_INIT( 5), PACA_INIT( 6), PACA_INIT( 7),
#if NR_CPUS > 8
- PACAINITDATA( 8, 0, NULL, 0, 0),
- PACAINITDATA( 9, 0, NULL, 0, 0),
- PACAINITDATA(10, 0, NULL, 0, 0),
- PACAINITDATA(11, 0, NULL, 0, 0),
- PACAINITDATA(12, 0, NULL, 0, 0),
- PACAINITDATA(13, 0, NULL, 0, 0),
- PACAINITDATA(14, 0, NULL, 0, 0),
- PACAINITDATA(15, 0, NULL, 0, 0),
- PACAINITDATA(16, 0, NULL, 0, 0),
- PACAINITDATA(17, 0, NULL, 0, 0),
- PACAINITDATA(18, 0, NULL, 0, 0),
- PACAINITDATA(19, 0, NULL, 0, 0),
- PACAINITDATA(20, 0, NULL, 0, 0),
- PACAINITDATA(21, 0, NULL, 0, 0),
- PACAINITDATA(22, 0, NULL, 0, 0),
- PACAINITDATA(23, 0, NULL, 0, 0),
- PACAINITDATA(24, 0, NULL, 0, 0),
- PACAINITDATA(25, 0, NULL, 0, 0),
- PACAINITDATA(26, 0, NULL, 0, 0),
- PACAINITDATA(27, 0, NULL, 0, 0),
- PACAINITDATA(28, 0, NULL, 0, 0),
- PACAINITDATA(29, 0, NULL, 0, 0),
- PACAINITDATA(30, 0, NULL, 0, 0),
- PACAINITDATA(31, 0, NULL, 0, 0),
+ PACA_INIT( 8), PACA_INIT( 9), PACA_INIT( 10), PACA_INIT( 11),
+ PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15),
+ PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19),
+ PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23),
+ PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27),
+ PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31),
#if NR_CPUS > 32
- PACAINITDATA(32, 0, NULL, 0, 0),
- PACAINITDATA(33, 0, NULL, 0, 0),
- PACAINITDATA(34, 0, NULL, 0, 0),
- PACAINITDATA(35, 0, NULL, 0, 0),
- PACAINITDATA(36, 0, NULL, 0, 0),
- PACAINITDATA(37, 0, NULL, 0, 0),
- PACAINITDATA(38, 0, NULL, 0, 0),
- PACAINITDATA(39, 0, NULL, 0, 0),
- PACAINITDATA(40, 0, NULL, 0, 0),
- PACAINITDATA(41, 0, NULL, 0, 0),
- PACAINITDATA(42, 0, NULL, 0, 0),
- PACAINITDATA(43, 0, NULL, 0, 0),
- PACAINITDATA(44, 0, NULL, 0, 0),
- PACAINITDATA(45, 0, NULL, 0, 0),
- PACAINITDATA(46, 0, NULL, 0, 0),
- PACAINITDATA(47, 0, NULL, 0, 0),
- PACAINITDATA(48, 0, NULL, 0, 0),
- PACAINITDATA(49, 0, NULL, 0, 0),
- PACAINITDATA(50, 0, NULL, 0, 0),
- PACAINITDATA(51, 0, NULL, 0, 0),
- PACAINITDATA(52, 0, NULL, 0, 0),
- PACAINITDATA(53, 0, NULL, 0, 0),
- PACAINITDATA(54, 0, NULL, 0, 0),
- PACAINITDATA(55, 0, NULL, 0, 0),
- PACAINITDATA(56, 0, NULL, 0, 0),
- PACAINITDATA(57, 0, NULL, 0, 0),
- PACAINITDATA(58, 0, NULL, 0, 0),
- PACAINITDATA(59, 0, NULL, 0, 0),
- PACAINITDATA(60, 0, NULL, 0, 0),
- PACAINITDATA(61, 0, NULL, 0, 0),
- PACAINITDATA(62, 0, NULL, 0, 0),
- PACAINITDATA(63, 0, NULL, 0, 0),
+ PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35),
+ PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39),
+ PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43),
+ PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47),
+ PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51),
+ PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55),
+ PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59),
+ PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63),
#if NR_CPUS > 64
- PACAINITDATA(64, 0, NULL, 0, 0),
- PACAINITDATA(65, 0, NULL, 0, 0),
- PACAINITDATA(66, 0, NULL, 0, 0),
- PACAINITDATA(67, 0, NULL, 0, 0),
- PACAINITDATA(68, 0, NULL, 0, 0),
- PACAINITDATA(69, 0, NULL, 0, 0),
- PACAINITDATA(70, 0, NULL, 0, 0),
- PACAINITDATA(71, 0, NULL, 0, 0),
- PACAINITDATA(72, 0, NULL, 0, 0),
- PACAINITDATA(73, 0, NULL, 0, 0),
- PACAINITDATA(74, 0, NULL, 0, 0),
- PACAINITDATA(75, 0, NULL, 0, 0),
- PACAINITDATA(76, 0, NULL, 0, 0),
- PACAINITDATA(77, 0, NULL, 0, 0),
- PACAINITDATA(78, 0, NULL, 0, 0),
- PACAINITDATA(79, 0, NULL, 0, 0),
- PACAINITDATA(80, 0, NULL, 0, 0),
- PACAINITDATA(81, 0, NULL, 0, 0),
- PACAINITDATA(82, 0, NULL, 0, 0),
- PACAINITDATA(83, 0, NULL, 0, 0),
- PACAINITDATA(84, 0, NULL, 0, 0),
- PACAINITDATA(85, 0, NULL, 0, 0),
- PACAINITDATA(86, 0, NULL, 0, 0),
- PACAINITDATA(87, 0, NULL, 0, 0),
- PACAINITDATA(88, 0, NULL, 0, 0),
- PACAINITDATA(89, 0, NULL, 0, 0),
- PACAINITDATA(90, 0, NULL, 0, 0),
- PACAINITDATA(91, 0, NULL, 0, 0),
- PACAINITDATA(92, 0, NULL, 0, 0),
- PACAINITDATA(93, 0, NULL, 0, 0),
- PACAINITDATA(94, 0, NULL, 0, 0),
- PACAINITDATA(95, 0, NULL, 0, 0),
- PACAINITDATA(96, 0, NULL, 0, 0),
- PACAINITDATA(97, 0, NULL, 0, 0),
- PACAINITDATA(98, 0, NULL, 0, 0),
- PACAINITDATA(99, 0, NULL, 0, 0),
- PACAINITDATA(100, 0, NULL, 0, 0),
- PACAINITDATA(101, 0, NULL, 0, 0),
- PACAINITDATA(102, 0, NULL, 0, 0),
- PACAINITDATA(103, 0, NULL, 0, 0),
- PACAINITDATA(104, 0, NULL, 0, 0),
- PACAINITDATA(105, 0, NULL, 0, 0),
- PACAINITDATA(106, 0, NULL, 0, 0),
- PACAINITDATA(107, 0, NULL, 0, 0),
- PACAINITDATA(108, 0, NULL, 0, 0),
- PACAINITDATA(109, 0, NULL, 0, 0),
- PACAINITDATA(110, 0, NULL, 0, 0),
- PACAINITDATA(111, 0, NULL, 0, 0),
- PACAINITDATA(112, 0, NULL, 0, 0),
- PACAINITDATA(113, 0, NULL, 0, 0),
- PACAINITDATA(114, 0, NULL, 0, 0),
- PACAINITDATA(115, 0, NULL, 0, 0),
- PACAINITDATA(116, 0, NULL, 0, 0),
- PACAINITDATA(117, 0, NULL, 0, 0),
- PACAINITDATA(118, 0, NULL, 0, 0),
- PACAINITDATA(119, 0, NULL, 0, 0),
- PACAINITDATA(120, 0, NULL, 0, 0),
- PACAINITDATA(121, 0, NULL, 0, 0),
- PACAINITDATA(122, 0, NULL, 0, 0),
- PACAINITDATA(123, 0, NULL, 0, 0),
- PACAINITDATA(124, 0, NULL, 0, 0),
- PACAINITDATA(125, 0, NULL, 0, 0),
- PACAINITDATA(126, 0, NULL, 0, 0),
- PACAINITDATA(127, 0, NULL, 0, 0),
+ PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67),
+ PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71),
+ PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75),
+ PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79),
+ PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83),
+ PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87),
+ PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91),
+ PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95),
+ PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99),
+ PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103),
+ PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107),
+ PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111),
+ PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115),
+ PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119),
+ PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123),
+ PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127),
#endif
#endif
#endif
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index 580676f87d2..ae6f579d3fa 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -351,7 +351,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
*offset += hose->pci_mem_offset;
res_bit = IORESOURCE_MEM;
} else {
- io_offset = (unsigned long)hose->io_base_virt;
+ io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
*offset += io_offset;
res_bit = IORESOURCE_IO;
}
@@ -378,7 +378,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
/* found it! construct the final physical address */
if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - io_offset;
+ *offset += hose->io_base_phys - io_offset;
return rp;
}
@@ -944,4 +944,22 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
}
EXPORT_SYMBOL(pci_read_irq_line);
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ unsigned long offset = 0;
+
+ if (hose == NULL)
+ return;
+
+ if (rsrc->flags & IORESOURCE_IO)
+ offset = pci_io_base - (unsigned long)hose->io_base_virt +
+ hose->io_base_phys;
+
+ *start = rsrc->start + offset;
+ *end = rsrc->end + offset;
+}
+
#endif /* CONFIG_PPC_MULTIPLATFORM */
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index 6cf03d387b9..3013cdb5f93 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -186,6 +186,8 @@ void __init pmac_setup_arch(void)
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
+
+ printk(KERN_INFO "Using native/NAP idle loop\n");
}
#ifdef CONFIG_SCSI
@@ -507,5 +509,6 @@ struct machdep_calls __initdata pmac_md = {
.calibrate_decr = pmac_calibrate_decr,
.feature_call = pmac_do_feature_call,
.progress = pmac_progress,
- .check_legacy_ioport = pmac_check_legacy_ioport
+ .check_legacy_ioport = pmac_check_legacy_ioport,
+ .idle_loop = native_idle,
};
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
index b230a63fe4c..705742f4eec 100644
--- a/arch/ppc64/kernel/ppc_ksyms.c
+++ b/arch/ppc64/kernel/ppc_ksyms.c
@@ -75,6 +75,7 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(giveup_altivec);
#endif
EXPORT_SYMBOL(__flush_icache_range);
+EXPORT_SYMBOL(flush_dcache_range);
#ifdef CONFIG_SMP
#ifdef CONFIG_PPC_ISERIES
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index aba89554d89..f7cae05e40f 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -36,6 +36,7 @@
#include <linux/kallsyms.h>
#include <linux/interrupt.h>
#include <linux/utsname.h>
+#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -307,6 +308,8 @@ void show_regs(struct pt_regs * regs)
void exit_thread(void)
{
+ kprobe_flush_task(current);
+
#ifndef CONFIG_SMP
if (last_task_used_math == current)
last_task_used_math = NULL;
@@ -321,6 +324,7 @@ void flush_thread(void)
{
struct thread_info *t = current_thread_info();
+ kprobe_flush_task(current);
if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index d5e4866e9ac..d1b33f0b26c 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -96,7 +96,6 @@ extern void udbg_init_maple_realmode(void);
extern unsigned long klimit;
extern void mm_init_ppc64(void);
-extern int idle_setup(void);
extern void stab_initialize(unsigned long stab);
extern void htab_initialize(void);
extern void early_init_devtree(void *flat_dt);
@@ -1081,8 +1080,11 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
- /* Select the correct idle loop for the platform. */
- idle_setup();
+ /* Use the default idle loop if the platform hasn't provided one. */
+ if (NULL == ppc_md.idle_loop) {
+ ppc_md.idle_loop = default_idle;
+ printk(KERN_INFO "Using default idle loop\n");
+ }
paging_init();
ppc64_boot_msg(0x15, "Setup Done");
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 118436e8085..206619080e6 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -30,47 +30,26 @@
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
-#include <linux/slab.h>
-#include <linux/uio.h>
-#include <linux/aio.h>
-#include <linux/nfs_fs.h>
-#include <linux/module.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/syscall.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
-#include <linux/filter.h>
-#include <linux/highmem.h>
-#include <linux/highuid.h>
#include <linux/mman.h>
-#include <linux/ipv6.h>
#include <linux/in.h>
-#include <linux/icmpv6.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/sysctl.h>
#include <linux/binfmts.h>
-#include <linux/dnotify.h>
#include <linux/security.h>
#include <linux/compat.h>
#include <linux/ptrace.h>
-#include <linux/aio_abi.h>
#include <linux/elf.h>
-#include <net/scm.h>
-#include <net/sock.h>
-
#include <asm/ptrace.h>
#include <asm/types.h>
#include <asm/ipc.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/semaphore.h>
-#include <asm/ppcdebug.h>
#include <asm/time.h>
#include <asm/mmu_context.h>
#include <asm/systemcfg.h>
@@ -350,8 +329,6 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
return ret;
}
-
-/* These are here just in case some old sparc32 binary calls it. */
asmlinkage long sys32_pause(void)
{
current->state = TASK_INTERRUPTIBLE;
@@ -360,8 +337,6 @@ asmlinkage long sys32_pause(void)
return -ERESTARTNOHAND;
}
-
-
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
@@ -847,16 +822,6 @@ asmlinkage long sys32_getpgid(u32 pid)
}
-/* Note: it is necessary to treat which and who as unsigned ints,
- * with the corresponding cast to a signed int to insure that the
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long sys32_getpriority(u32 which, u32 who)
-{
- return sys_getpriority((int)which, (int)who);
-}
-
/* Note: it is necessary to treat pid as an unsigned int,
* with the corresponding cast to a signed int to insure that the
@@ -1048,6 +1013,11 @@ asmlinkage long sys32_setpgid(u32 pid, u32 pgid)
return sys_setpgid((int)pid, (int)pgid);
}
+long sys32_getpriority(u32 which, u32 who)
+{
+ /* sign extend which and who */
+ return sys_getpriority((int)which, (int)who);
+}
long sys32_setpriority(u32 which, u32 who, u32 niceval)
{
@@ -1055,6 +1025,18 @@ long sys32_setpriority(u32 which, u32 who, u32 niceval)
return sys_setpriority((int)which, (int)who, (int)niceval);
}
+long sys32_ioprio_get(u32 which, u32 who)
+{
+ /* sign extend which and who */
+ return sys_ioprio_get((int)which, (int)who);
+}
+
+long sys32_ioprio_set(u32 which, u32 who, u32 ioprio)
+{
+ /* sign extend which, who and ioprio */
+ return sys_ioprio_set((int)which, (int)who, (int)ioprio);
+}
+
/* Note: it is necessary to treat newmask as an unsigned int,
* with the corresponding cast to a signed int to insure that the
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1273,8 +1255,6 @@ long ppc32_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
(u64)len_high << 32 | len_low, advice);
}
-extern asmlinkage long sys_timer_create(clockid_t, sigevent_t __user *, timer_t __user *);
-
long ppc32_timer_create(clockid_t clock,
struct compat_sigevent __user *ev32,
timer_t __user *timer_id)
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index c8fa6569b2f..02b8ac4e016 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -112,7 +112,6 @@ void ppc64_enable_pmcs(void)
unsigned long hid0;
#ifdef CONFIG_PPC_PSERIES
unsigned long set, reset;
- int ret;
#endif /* CONFIG_PPC_PSERIES */
/* Only need to enable them once */
@@ -145,11 +144,7 @@ void ppc64_enable_pmcs(void)
case PLATFORM_PSERIES_LPAR:
set = 1UL << 63;
reset = 0;
- ret = plpar_hcall_norets(H_PERFMON, set, reset);
- if (ret)
- printk(KERN_ERR "H_PERFMON call on cpu %u "
- "returned %d\n",
- smp_processor_id(), ret);
+ plpar_hcall_norets(H_PERFMON, set, reset);
break;
#endif /* CONFIG_PPC_PSERIES */
@@ -161,13 +156,6 @@ void ppc64_enable_pmcs(void)
/* instruct hypervisor to maintain PMCs */
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
get_paca()->lppaca.pmcregs_in_use = 1;
-
- /*
- * On SMT machines we have to set the run latch in the ctrl register
- * in order to make PMC6 spin.
- */
- if (cpu_has_feature(CPU_FTR_SMT))
- ppc64_runlatch_on();
#endif /* CONFIG_PPC_PSERIES */
}
@@ -400,7 +388,12 @@ static int __init topology_init(void)
struct cpu *c = &per_cpu(cpu_devices, cpu);
#ifdef CONFIG_NUMA
- parent = &node_devices[cpu_to_node(cpu)];
+ /* The node to which a cpu belongs can't be known
+ * until the cpu is made present.
+ */
+ parent = NULL;
+ if (cpu_present(cpu))
+ parent = &node_devices[cpu_to_node(cpu)];
#endif
/*
* For now, we just see if the system supports making
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 2348a75e050..909462e1ade 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -91,6 +91,7 @@ unsigned long tb_to_xs;
unsigned tb_to_us;
unsigned long processor_freq;
DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL_GPL(rtc_lock);
unsigned long tb_to_ns_scale;
unsigned long tb_to_ns_shift;
@@ -98,7 +99,6 @@ unsigned long tb_to_ns_shift;
struct gettimeofday_struct do_gtod;
extern unsigned long wall_jiffies;
-extern unsigned long lpevent_count;
extern int smp_tb_synchronized;
extern struct timezone sys_tz;
@@ -366,11 +366,8 @@ int timer_interrupt(struct pt_regs * regs)
set_dec(next_dec);
#ifdef CONFIG_PPC_ISERIES
- {
- struct ItLpQueue *lpq = lpaca->lpqueue_ptr;
- if (lpq && ItLpQueue_isLpIntPending(lpq))
- lpevent_count += ItLpQueue_process(lpq, regs);
- }
+ if (hvlpevent_is_pending())
+ process_hvlpevents(regs);
#endif
/* collect purr register values often, for accurate calculations */
diff --git a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/ppc64/kernel/vdso32/vdso32.lds.S
index 11290c902ba..6f87a916a39 100644
--- a/arch/ppc64/kernel/vdso32/vdso32.lds.S
+++ b/arch/ppc64/kernel/vdso32/vdso32.lds.S
@@ -40,9 +40,9 @@ SECTIONS
.gcc_except_table : { *(.gcc_except_table) }
.fixup : { *(.fixup) }
- .got ALIGN(4) : { *(.got.plt) *(.got) }
-
.dynamic : { *(.dynamic) } :text :dynamic
+ .got : { *(.got) }
+ .plt : { *(.plt) }
_end = .;
__end = .;