[ppc46] SMT processor support and logical cpu numbering, from Dave Engebretsen

And SMT processor support & move back to a logical cpu numbering
in support of DLPAR work.


---

 arch/ppc64/kernel/idle.c      |    0 
 arch/ppc64/kernel/open_pic.c  |   31 ++++-
 arch/ppc64/kernel/prom.c      |  228 +++++++++++++++++++++++++++++++++---------
 arch/ppc64/kernel/setup.c     |   24 +++-
 arch/ppc64/kernel/smp.c       |    7 +
 arch/ppc64/kernel/xics.c      |   10 -
 include/asm-ppc64/paca.h      |    2 
 include/asm-ppc64/processor.h |    1 
 include/asm-ppc64/smp.h       |   23 ++++
 9 files changed, 259 insertions(+), 67 deletions(-)

diff -puN arch/ppc64/kernel/idle.c~ppc64-logical_cpu arch/ppc64/kernel/idle.c
diff -puN arch/ppc64/kernel/open_pic.c~ppc64-logical_cpu arch/ppc64/kernel/open_pic.c
--- 25/arch/ppc64/kernel/open_pic.c~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/open_pic.c	2004-01-13 23:22:45.000000000 -0800
@@ -85,10 +85,10 @@ unsigned int openpic_vec_spurious;
  */
 #ifdef CONFIG_SMP
 #define THIS_CPU		Processor[cpu]
-#define DECL_THIS_CPU		int cpu = smp_processor_id()
+#define DECL_THIS_CPU		int cpu = hard_smp_processor_id()
 #define CHECK_THIS_CPU		check_arg_cpu(cpu)
 #else
-#define THIS_CPU		Processor[smp_processor_id()]
+#define THIS_CPU		Processor[hard_smp_processor_id()]
 #define DECL_THIS_CPU
 #define CHECK_THIS_CPU
 #endif /* CONFIG_SMP */
@@ -355,7 +355,7 @@ void __init openpic_init(int main_pic, i
 	/* SIOint (8259 cascade) is special */
 	if (offset) {
 		openpic_initirq(0, 8, offset, 1, 1);
-		openpic_mapirq(0, 1 << boot_cpuid);
+		openpic_mapirq(0, 1 << get_hard_smp_processor_id(boot_cpuid));
 	}
 
 	/* Init all external sources */
@@ -373,7 +373,7 @@ void __init openpic_init(int main_pic, i
 		/* Enabled, Priority 8 or 9 */
 		openpic_initirq(i, pri, i+offset, !sense, sense);
 		/* Processor 0 */
-		openpic_mapirq(i, 1 << boot_cpuid);
+		openpic_mapirq(i, 1 << get_hard_smp_processor_id(boot_cpuid));
 	}
 
 	/* Init descriptors */
@@ -514,10 +514,23 @@ static void openpic_set_spurious(u_int v
 			   vec);
 }
 
+/*
+ * Convert a cpu mask from logical to physical cpu numbers.
+ */
+static inline u32 physmask(u32 cpumask)
+{
+	int i;
+	u32 mask = 0;
+
+	for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
+		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
+	return mask;
+}
+
 void openpic_init_processor(u_int cpumask)
 {
 	openpic_write(&OpenPIC->Global.Processor_Initialization,
-		      cpumask & cpus_coerce(cpu_online_map));
+		      physmask(cpumask & cpus_coerce(cpu_online_map)));
 }
 
 #ifdef CONFIG_SMP
@@ -551,7 +564,7 @@ void openpic_cause_IPI(u_int ipi, u_int 
 	CHECK_THIS_CPU;
 	check_arg_ipi(ipi);
 	openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
-		      cpumask & cpus_coerce(cpu_online_map));
+		      physmask(cpumask & cpus_coerce(cpu_online_map)));
 }
 
 void openpic_request_IPIs(void)
@@ -592,7 +605,7 @@ void __devinit do_openpic_setup_cpu(void
 {
 #ifdef CONFIG_IRQ_ALL_CPUS
  	int i;
-	u32 msk = 1 << smp_processor_id();
+	u32 msk = 1 << hard_smp_processor_id();
 #endif
 
 	spin_lock(&openpic_setup_lock);
@@ -637,7 +650,7 @@ static void __init openpic_maptimer(u_in
 {
 	check_arg_timer(timer);
 	openpic_write(&OpenPIC->Global.Timer[timer].Destination,
-		      cpumask & cpus_coerce(cpu_online_map));
+		      physmask(cpumask & cpus_coerce(cpu_online_map)));
 }
 
 
@@ -763,7 +776,7 @@ static void openpic_set_affinity(unsigne
 	cpumask_t tmp;
 
 	cpus_and(tmp, cpumask, cpu_online_map);
-	openpic_mapirq(irq_nr - open_pic_irq_offset, cpus_coerce(tmp));
+	openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpus_coerce(tmp)));
 }
 
 #ifdef CONFIG_SMP
diff -puN arch/ppc64/kernel/prom.c~ppc64-logical_cpu arch/ppc64/kernel/prom.c
--- 25/arch/ppc64/kernel/prom.c~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/prom.c	2004-01-13 23:22:45.000000000 -0800
@@ -149,6 +149,7 @@ char *bootpath = 0;
 char *bootdevice = 0;
 
 int boot_cpuid = 0;
+#define MAX_CPU_THREADS 2
 
 struct device_node *allnodes = 0;
 /* use when traversing tree through the allnext, child, sibling,
@@ -898,16 +899,21 @@ static void
 prom_hold_cpus(unsigned long mem)
 {
 	unsigned long i;
-	unsigned int cpuid;
+	unsigned int reg;
 	phandle node;
 	unsigned long offset = reloc_offset();
 	char type[64], *path;
+	int cpuid = 0;
+	unsigned int interrupt_server[MAX_CPU_THREADS];
+	unsigned int cpu_threads, hw_cpu_num;
+	int propsize;
 	extern void __secondary_hold(void);
         extern unsigned long __secondary_hold_spinloop;
         extern unsigned long __secondary_hold_acknowledge;
         unsigned long *spinloop     = __v2a(&__secondary_hold_spinloop);
         unsigned long *acknowledge  = __v2a(&__secondary_hold_acknowledge);
         unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold));
+        struct naca_struct *_naca = RELOC(naca);
         struct systemcfg *_systemcfg = RELOC(systemcfg);
 	struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
 	struct prom_t *_prom = PTRRELOC(&prom);
@@ -960,13 +966,9 @@ prom_hold_cpus(unsigned long mem)
 		if (strcmp(type, RELOC("okay")) != 0)
 			continue;
 
-                cpuid = -1;
+                reg = -1;
 		call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
-			  &cpuid, sizeof(cpuid));
-
-		/* Only need to start secondary procs, not ourself. */
-		if ( cpuid == _prom->cpu )
-			continue;
+			  &reg, sizeof(reg));
 
 		path = (char *) mem;
 		memset(path, 0, 256);
@@ -976,12 +978,14 @@ prom_hold_cpus(unsigned long mem)
 
 #ifdef DEBUG_PROM
 		prom_print_nl();
-		prom_print(RELOC("cpu hw idx   = 0x"));
+		prom_print(RELOC("cpuid        = 0x"));
 		prom_print_hex(cpuid);
 		prom_print_nl();
+		prom_print(RELOC("cpu hw idx   = 0x"));
+		prom_print_hex(reg);
+		prom_print_nl();
 #endif
-		prom_print(RELOC("starting cpu "));
-		prom_print(path);
+		_xPaca[cpuid].xHwProcNum = reg;
 
 		/* Init the acknowledge var which will be reset by
 		 * the secondary cpu when it awakens from its OF
@@ -989,45 +993,80 @@ prom_hold_cpus(unsigned long mem)
 		 */
 		*acknowledge = (unsigned long)-1;
 
-#ifdef DEBUG_PROM
-		prom_print(RELOC("    3) spinloop       = 0x"));
-		prom_print_hex(spinloop);
-		prom_print_nl();
-		prom_print(RELOC("    3) *spinloop      = 0x"));
-		prom_print_hex(*spinloop);
-		prom_print_nl();
-		prom_print(RELOC("    3) acknowledge    = 0x"));
-		prom_print_hex(acknowledge);
-		prom_print_nl();
-		prom_print(RELOC("    3) *acknowledge   = 0x"));
-		prom_print_hex(*acknowledge);
-		prom_print_nl();
-		prom_print(RELOC("    3) secondary_hold = 0x"));
-		prom_print_hex(secondary_hold);
+		propsize = call_prom(RELOC("getprop"), 4, 1, node,
+				     RELOC("ibm,ppc-interrupt-server#s"), 
+				     &interrupt_server, 
+				     sizeof(interrupt_server));
+		if (propsize < 0) {
+			/* no property.  old hardware has no SMT */
+			cpu_threads = 1;
+			interrupt_server[0] = reg; /* fake it with phys id */
+		} else {
+			/* We have a threaded processor */
+			cpu_threads = propsize / sizeof(u32);
+			if (cpu_threads > MAX_CPU_THREADS) {
+				prom_print(RELOC("SMT: too many threads!\nSMT: found "));
+				prom_print_hex(cpu_threads);
+				prom_print(RELOC(", max is "));
+				prom_print_hex(MAX_CPU_THREADS);
 		prom_print_nl();
-#endif
-		call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid);
+				cpu_threads = 1; /* ToDo: panic? */
+			}
+		}
+
+		hw_cpu_num = interrupt_server[0];
+		if (hw_cpu_num != _prom->cpu) {
+			/* Primary Thread of non-boot cpu */
+			prom_print_hex(cpuid);
+			prom_print(RELOC(" : starting cpu "));
+			prom_print(path);
 		prom_print(RELOC("..."));
+			call_prom(RELOC("start-cpu"), 3, 0, node, 
+				  secondary_hold, cpuid);
+
 		for ( i = 0 ; (i < 100000000) && 
 			      (*acknowledge == ((unsigned long)-1)); i++ ) ;
-#ifdef DEBUG_PROM
-		{
-			unsigned long *p = 0x0;
-			prom_print(RELOC("    4) 0x0 = 0x"));
-			prom_print_hex(*p);
-			prom_print_nl();
-		}
-#endif
+
 		if (*acknowledge == cpuid) {
 			prom_print(RELOC("ok\n"));
 			/* Set the number of active processors. */
 			_systemcfg->processorCount++;
-			_xPaca[cpuid].active = 1;
+				cpu_set(cpuid, RELOC(cpu_available_map));
+				cpu_set(cpuid, RELOC(cpu_possible_map));
+				cpu_set(cpuid, RELOC(cpu_present_at_boot));
 		} else {
 			prom_print(RELOC("failed: "));
 			prom_print_hex(*acknowledge);
 			prom_print_nl();
+				/* prom_panic(RELOC("cpu failed to start")); */
+		}
+		} else {
+			prom_print_hex(cpuid);
+			prom_print(RELOC(" : booting  cpu "));
+			prom_print(path);
+			prom_print_nl();
+			cpu_set(cpuid, RELOC(cpu_available_map));
+			cpu_set(cpuid, RELOC(cpu_possible_map));
+			cpu_set(cpuid, RELOC(cpu_online_map));
+			cpu_set(cpuid, RELOC(cpu_present_at_boot));
+		}
+
+		/* Init paca for secondary threads.   They start later. */
+		for (i=1; i < cpu_threads; i++) {
+			cpuid++;
+			_xPaca[cpuid].xHwProcNum = interrupt_server[i];
+			prom_print_hex(interrupt_server[i]);
+			prom_print(RELOC(" : preparing thread ... "));
+			if (_naca->smt_state) {
+				cpu_set(cpuid, RELOC(cpu_available_map));
+				cpu_set(cpuid, RELOC(cpu_present_at_boot));
+				prom_print(RELOC("available"));
+			} else {
+				prom_print(RELOC("not available"));
+			}
+			prom_print_nl();
 		}
+		cpuid++;
 	}
 #ifdef CONFIG_HMT
 	/* Only enable HMT on processors that provide support. */
@@ -1037,10 +1076,10 @@ prom_hold_cpus(unsigned long mem)
 		prom_print(RELOC("    starting secondary threads\n"));
 
 		for (i = 0; i < NR_CPUS; i += 2) {
-			if (!_xPaca[i].active)
+			if (!cpu_online(i))
 				continue;
 
-			if (i == boot_cpuid) {
+			if (i == 0) {
 				unsigned long pir = _get_PIR();
 				if (__is_processor(PV_PULSAR)) {
 					RELOC(hmt_thread_data)[i].pir = 
@@ -1050,7 +1089,8 @@ prom_hold_cpus(unsigned long mem)
 						pir & 0x3ff;
 				}
 			}
-			_xPaca[i+1].active = 1;
+/* 			cpu_set(i+1, cpu_online_map); */
+			cpu_set(i+1, RELOC(cpu_possible_map));
 		}
 		_systemcfg->processorCount *= 2;
 	} else {
@@ -1063,6 +1103,105 @@ prom_hold_cpus(unsigned long mem)
 #endif
 }
 
+static void
+smt_setup(void)
+{
+	char *p, *q;
+	char my_smt_enabled = SMT_DYNAMIC;
+	unsigned long my_smt_snooze_delay; 
+	ihandle prom_options = NULL;
+	char option[9];
+	unsigned long offset = reloc_offset();
+        struct naca_struct *_naca = RELOC(naca);
+	char found = 0;
+
+	if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) {
+		for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) {
+			q = p + 12;
+			if (p > RELOC(cmd_line) && p[-1] != ' ')
+				continue;
+			found = 1;
+			if (q[0] == 'o' && q[1] == 'f' && 
+			    q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) {
+				my_smt_enabled = SMT_OFF;
+			} else if (q[0]=='o' && q[1] == 'n' && 
+				   (q[2] == ' ' || q[2] == '\0')) {
+				my_smt_enabled = SMT_ON;
+			} else {
+				my_smt_enabled = SMT_DYNAMIC;
+			} 
+		}
+	}
+	if (!found) {
+		prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));
+		if (prom_options != (ihandle) -1) {
+			call_prom(RELOC("getprop"), 
+				4, 1, prom_options,
+				RELOC("ibm,smt-enabled"), 
+				option, 
+				sizeof(option));
+			if (option[0] != 0) {
+				found = 1;
+				if (!strcmp(option, "off"))	
+					my_smt_enabled = SMT_OFF;
+				else if (!strcmp(option, "on"))	
+					my_smt_enabled = SMT_ON;
+				else
+					my_smt_enabled = SMT_DYNAMIC;
+			}
+		}
+	}
+
+	if (!found )
+		my_smt_enabled = SMT_DYNAMIC; /* default to on */
+
+	found = 0;
+	if (my_smt_enabled) {
+		if (strstr(RELOC(cmd_line), RELOC("smt-snooze-delay="))) {
+			for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-snooze-delay="))) != 0; ) {
+				q = p + 17;
+				if (p > RELOC(cmd_line) && p[-1] != ' ')
+					continue;
+				found = 1;
+				/* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */
+				my_smt_snooze_delay = 0;
+				while (*q >= '0' && *q <= '9') {
+					my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';
+					q++;
+				}
+			}
+		}
+
+		if (!found) {
+			prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));
+			if (prom_options != (ihandle) -1) {
+				call_prom(RELOC("getprop"), 
+					4, 1, prom_options,
+					RELOC("ibm,smt-snooze-delay"), 
+					option, 
+					sizeof(option));
+				if (option[0] != 0) {
+					found = 1;
+					/* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */
+					my_smt_snooze_delay = 0;
+					q = option;
+					while (*q >= '0' && *q <= '9') {
+						my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';
+						q++;
+					}
+				}
+			}
+		}
+
+		if (!found) {
+			my_smt_snooze_delay = 30000; /* default value */
+		}
+	} else {
+		my_smt_snooze_delay = 0; /* default value */
+	}
+	_naca->smt_snooze_delay = my_smt_snooze_delay;
+	_naca->smt_state = my_smt_enabled;
+}
 
 /*
  * We enter here early on, when the Open Firmware prom is still
@@ -1145,11 +1284,9 @@ prom_init(unsigned long r3, unsigned lon
 		cpu_pkg, RELOC("reg"),
 		&getprop_rval, sizeof(getprop_rval));
 	_prom->cpu = (int)(unsigned long)getprop_rval;
-	_xPaca[_prom->cpu].active = 1;
-#ifdef CONFIG_SMP
-	cpu_set(_prom->cpu, RELOC(cpu_online_map));
-#endif
-	RELOC(boot_cpuid) = _prom->cpu;
+	_xPaca[0].xHwProcNum = _prom->cpu;
+
+	RELOC(boot_cpuid) = 0;
 
 #ifdef DEBUG_PROM
   	prom_print(RELOC("Booting CPU hw index = 0x"));
@@ -1183,11 +1320,12 @@ prom_init(unsigned long r3, unsigned lon
         /* Initialize some system info into the Naca early... */
         mem = prom_initialize_naca(mem);
 
+	smt_setup();
+	
         /* If we are on an SMP machine, then we *MUST* do the
          * following, regardless of whether we have an SMP
          * kernel or not.
          */
-        if (_systemcfg->processorCount > 1)
 	        prom_hold_cpus(mem);
 
 #ifdef DEBUG_PROM
diff -puN arch/ppc64/kernel/setup.c~ppc64-logical_cpu arch/ppc64/kernel/setup.c
--- 25/arch/ppc64/kernel/setup.c~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/setup.c	2004-01-13 23:22:45.000000000 -0800
@@ -58,6 +58,8 @@ extern void iSeries_init_early( void );
 extern void pSeries_init_early( void );
 extern void pSeriesLP_init_early(void);
 extern void mm_init_ppc64( void ); 
+extern void pseries_secondary_smp_init(unsigned long); 
+extern int  idle_setup(void);
 extern void vpa_init(int cpu);
 
 unsigned long decr_overclock = 1;
@@ -144,6 +146,8 @@ void __init disable_early_printk(void)
 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
 		  unsigned long r6, unsigned long r7)
 {
+        unsigned int ret, i;
+
 #ifdef CONFIG_XMON_DEFAULT
 	debugger = xmon;
 	debugger_bpt = xmon_bpt;
@@ -187,6 +191,21 @@ void setup_system(unsigned long r3, unsi
 	if (systemcfg->platform & PLATFORM_PSERIES) {
 		early_console_initialized = 1;
 		register_console(&udbg_console);
+		finish_device_tree();
+		chrp_init(r3, r4, r5, r6, r7);
+
+		/* Start secondary threads on SMT systems */
+		for (i = 0; i < NR_CPUS; i++) {
+			if(cpu_available(i)  && !cpu_possible(i)) {
+				printk("%16.16x : starting thread\n", i);
+				rtas_call(rtas_token("start-cpu"), 3, 1, 
+					  (void *)&ret,
+					  get_hard_smp_processor_id(i), 
+					  *((unsigned long *)pseries_secondary_smp_init), i);
+				cpu_set(i, cpu_possible_map);
+				systemcfg->processorCount++;
+			}
+		}
 	}
 
 	printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
@@ -205,11 +224,6 @@ void setup_system(unsigned long r3, unsi
 	printk("htab_data.num_ptegs           = 0x%lx\n", htab_data.htab_num_ptegs);
 	printk("-----------------------------------------------------\n");
 
-	if (systemcfg->platform & PLATFORM_PSERIES) {
-		finish_device_tree();
-		chrp_init(r3, r4, r5, r6, r7);
-	}
-
 	mm_init_ppc64();
 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
diff -puN arch/ppc64/kernel/smp.c~ppc64-logical_cpu arch/ppc64/kernel/smp.c
--- 25/arch/ppc64/kernel/smp.c~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/smp.c	2004-01-13 23:22:45.000000000 -0800
@@ -53,8 +53,11 @@
 int smp_threads_ready;
 unsigned long cache_decay_ticks;
 
-/* initialised so it doesn't end up in bss */
+/* Initialised so it doesn't end up in bss */
+cpumask_t cpu_possible_map    = CPU_MASK_NONE;
 cpumask_t cpu_online_map = CPU_MASK_NONE;
+cpumask_t cpu_available_map   = CPU_MASK_NONE;
+cpumask_t cpu_present_at_boot = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
 
@@ -67,6 +70,8 @@ extern unsigned char stab_array[];
 extern int cpu_idle(void *unused);
 void smp_call_function_interrupt(void);
 void smp_message_pass(int target, int msg, unsigned long data, int wait);
+extern long register_vpa(unsigned long flags, unsigned long proc,
+			 unsigned long vpa);
 
 #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w))
 
diff -puN include/asm-ppc64/paca.h~ppc64-logical_cpu include/asm-ppc64/paca.h
--- 25/include/asm-ppc64/paca.h~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/include/asm-ppc64/paca.h	2004-01-13 23:22:45.000000000 -0800
@@ -61,7 +61,7 @@ struct paca_struct {
 	struct ItLpRegSave *xLpRegSavePtr; /* Pointer to LpRegSave for PLIC	0x08 */
 	u64 xCurrent;  		        /* Pointer to current			0x10 */
 	u16 xPacaIndex;			/* Logical processor number		0x18 */
-	u16 active;			/* Is this cpu active?			0x1a */
+        u16 xHwProcNum;                 /* Physical processor number            0x1A */
 	u32 default_decr;		/* Default decrementer value		0x1c */	
 	u64 unused1;
 	u64 xKsave;			/* Saved Kernel stack addr or zero	0x28 */
diff -puN include/asm-ppc64/smp.h~ppc64-logical_cpu include/asm-ppc64/smp.h
--- 25/include/asm-ppc64/smp.h~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/include/asm-ppc64/smp.h	2004-01-13 23:22:45.000000000 -0800
@@ -34,9 +34,28 @@ extern void smp_send_xmon_break(int cpu)
 struct pt_regs;
 extern void smp_message_recv(int, struct pt_regs *);
 
-#define cpu_possible(cpu)	paca[cpu].active
 
 #define smp_processor_id() (get_paca()->xPacaIndex)
+#define hard_smp_processor_id() (get_paca()->xHwProcNum)
+
+/*
+ * Retrieve the state of a CPU:
+ * online:          CPU is in a normal run state
+ * possible:        CPU is a candidate to be made online
+ * available:       CPU is candidate for the 'possible' pool
+ *                  Used to get SMT threads started at boot time.
+ * present_at_boot: CPU was available at boot time.  Used in DLPAR
+ *                  code to handle special cases for processor start up.
+ */
+extern cpumask_t cpu_present_at_boot;
+extern cpumask_t cpu_online_map;
+extern cpumask_t cpu_possible_map;
+extern cpumask_t cpu_available_map;
+
+#define cpu_present_at_boot(cpu) cpu_isset(cpu, cpu_present_at_boot)
+#define cpu_online(cpu)          cpu_isset(cpu, cpu_online_map) 
+#define cpu_possible(cpu)        cpu_isset(cpu, cpu_possible_map) 
+#define cpu_available(cpu)       cpu_isset(cpu, cpu_available_map) 
 
 /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
  *
@@ -52,5 +71,7 @@ void smp_init_pSeries(void);
 
 #endif /* __ASSEMBLY__ */
 #endif /* !(CONFIG_SMP) */
+#define get_hard_smp_processor_id(CPU) (paca[(CPU)].xHwProcNum)
+#define set_hard_smp_processor_id(CPU, VAL) do { (paca[(CPU)].xHwProcNum = VAL); } while (0)
 #endif /* !(_PPC64_SMP_H) */
 #endif /* __KERNEL__ */
diff -puN include/asm-ppc64/processor.h~ppc64-logical_cpu include/asm-ppc64/processor.h
--- 25/include/asm-ppc64/processor.h~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/include/asm-ppc64/processor.h	2004-01-13 23:22:45.000000000 -0800
@@ -371,6 +371,7 @@
 #define	PV_ICESTAR	0x0036
 #define	PV_SSTAR	0x0037
 #define	PV_POWER4p	0x0038
+#define	PV_POWER5	0x003A
 #define	PV_630        	0x0040
 #define	PV_630p	        0x0041
 
diff -puN arch/ppc64/kernel/xics.c~ppc64-logical_cpu arch/ppc64/kernel/xics.c
--- 25/arch/ppc64/kernel/xics.c~ppc64-logical_cpu	2004-01-13 23:22:45.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/xics.c	2004-01-13 23:22:45.000000000 -0800
@@ -202,7 +202,7 @@ static void pSeriesLP_qirr_info(int n_cp
 {
 	unsigned long lpar_rc;
 
-	lpar_rc = plpar_ipi(n_cpu, value);
+	lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
 	if (lpar_rc != H_Success)
 		panic("bad return code qirr - rc = %lx\n", lpar_rc); 
 }
@@ -441,7 +441,7 @@ nextnode:
 	     np;
 	     np = of_find_node_by_type(np, "cpu")) {
 		ireg = (uint *)get_property(np, "reg", &ilen);
-		if (ireg && ireg[0] == smp_processor_id()) {
+		if (ireg && ireg[0] == hard_smp_processor_id()) {
 			ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
 			i = ilen / sizeof(int);
 			if (ireg && i > 0) {
@@ -478,8 +478,8 @@ nextnode:
 		for (i = 0; i < NR_CPUS; ++i) {
 			if (!cpu_possible(i))
 				continue;
-			xics_per_cpu[i] = __ioremap((ulong)inodes[i].addr, 
-						    (ulong)inodes[i].size,
+			xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
+						    (ulong)inodes[get_hard_smp_processor_id(i)].size,
 						    _PAGE_NO_CACHE);
 		}
 #else
@@ -570,7 +570,7 @@ void xics_set_affinity(unsigned int virq
 		cpus_and(tmp, cpu_online_map, cpumask);
 		if (cpus_empty(tmp))
 			goto out;
-		newmask = first_cpu(cpumask);
+		newmask = get_hard_smp_processor_id(first_cpu(cpumask));
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,

_