2 * BK Id: SCCS/s.iSeries_smp.c 1.6 11/08/01 22:41:15 paulus
5 * SMP support for iSeries/LPAR.
7 * Copyright (C) 2001 IBM Corp.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
15 #include <linux/config.h>
16 #include <linux/kernel.h>
17 #include <linux/sched.h>
18 #include <linux/smp.h>
19 #include <linux/smp_lock.h>
20 #include <linux/interrupt.h>
21 #include <linux/kernel_stat.h>
22 #include <linux/delay.h>
23 #define __KERNEL_SYSCALLS__
24 #include <linux/unistd.h>
25 #include <linux/init.h>
26 #include <linux/spinlock.h>
28 #include <asm/ptrace.h>
29 #include <asm/atomic.h>
32 #include <asm/pgtable.h>
33 #include <asm/hardirq.h>
34 #include <asm/softirq.h>
38 #include <asm/residual.h>
41 #include <asm/iSeries/LparData.h>
42 #include <asm/iSeries/HvCall.h>
43 extern u64 get_tb64(void);
44 extern u64 next_jiffy_update_tb[];
46 static unsigned long iSeries_smp_message[NR_CPUS];
48 void iSeries_smp_message_recv( struct pt_regs * regs )
50 int cpu = smp_processor_id();
53 if ( smp_num_cpus < 2 )
56 for ( msg = 0; msg < 4; ++msg )
57 if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )
58 smp_message_recv( msg, regs );
62 static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait)
65 for (i = 0; i < smp_num_cpus; ++i) {
66 if ( (target == MSG_ALL) ||
68 ((target == MSG_ALL_BUT_SELF) && (i != smp_processor_id())) ) {
69 set_bit( msg, &iSeries_smp_message[i] );
70 HvCall_sendIPI(&(xPaca[i]));
75 static int smp_iSeries_probe(void)
79 struct ItLpPaca * lpPaca;
82 for (i=0; i<maxPacas; ++i) {
83 lpPaca = xPaca[i].xLpPacaPtr;
84 if ( lpPaca->xDynProcStatus < 2 )
88 smp_tb_synchronized = 1;
92 extern unsigned long decr_overclock;
93 static void smp_iSeries_kick_cpu(int nr)
95 struct ItLpPaca * lpPaca;
96 // Verify we have a Paca for processor nr
100 // Verify that our partition has a processor nr
101 lpPaca = xPaca[nr].xLpPacaPtr;
102 if ( lpPaca->xDynProcStatus >= 2 )
104 xPaca[nr].default_decr = tb_ticks_per_jiffy / decr_overclock;
105 // The processor is currently spinning, waiting
106 // for the xProcStart field to become non-zero
107 // After we set xProcStart, the processor will
108 // continue on to secondary_start in iSeries_head.S
109 xPaca[nr].xProcStart = 1;
112 static void smp_iSeries_setup_cpu(int nr)
114 set_dec( xPaca[nr].default_decr );
117 void smp_iSeries_space_timers( unsigned nr )
121 offset = tb_ticks_per_jiffy / nr;
122 for ( i=1; i<nr; ++i ) {
123 next_jiffy_update_tb[i] = next_jiffy_update_tb[i-1] + offset;
127 struct smp_ops_t iSeries_smp_ops = {
128 smp_iSeries_message_pass,
130 smp_iSeries_kick_cpu,
131 smp_iSeries_setup_cpu