PowerPC common SMP startup and time base rework.

- make mftb() shared, rewrite in C, provide complementary mttb()
- adjust SMP startup per the above, additional comments, minor naming
  changes
- eliminate redundant TB defines, other minor cosmetics

Reviewed by:	marcel, nwhitehorn
Obtained from:	Freescale, Semihalf
This commit is contained in:
Rafal Jaworowski 2009-05-14 16:48:25 +00:00
parent 95b0b37cfc
commit 7ad9c533ef
6 changed files with 77 additions and 57 deletions

View File

@ -148,6 +148,14 @@ decr_init(void)
mtmsr(msr); mtmsr(msr);
} }
#ifdef SMP
void
decr_ap_init(void)
{
}
#endif
void void
decr_tc_init(void) decr_tc_init(void)
{ {
@ -155,17 +163,6 @@ decr_tc_init(void)
tc_init(&decr_timecounter); tc_init(&decr_timecounter);
} }
static __inline u_quad_t
mftb(void)
{
u_long scratch;
u_quad_t tb;
__asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
: "=r"(tb), "=r"(scratch));
return tb;
}
static unsigned static unsigned
decr_get_timecount(struct timecounter *tc) decr_get_timecount(struct timecounter *tc)
{ {

View File

@ -151,22 +151,6 @@ decr_init (void)
mtmsr(msr); mtmsr(msr);
} }
static __inline u_quad_t
mftb (void)
{
u_long scratch;
u_quad_t tb;
__asm__ __volatile__(
"1: mftbu %0;"
" mftb %0+1;"
" mftbu %1;"
" cmpw 0,%0,%1;"
" bne 1b"
: "=r"(tb), "=r"(scratch));
return tb;
}
void void
decr_tc_init(void) decr_tc_init(void)
{ {

View File

@ -115,13 +115,37 @@ mfdec(void)
static __inline register_t static __inline register_t
mfpvr(void) mfpvr(void)
{ {
register_t value; register_t value;
__asm __volatile ("mfpvr %0" : "=r"(value)); __asm __volatile ("mfpvr %0" : "=r"(value));
return (value); return (value);
} }
static __inline u_quad_t
mftb(void)
{
u_quad_t tb;
uint32_t *tbup = (uint32_t *)&tb;
uint32_t *tblp = tbup + 1;
do {
*tbup = mfspr(TBR_TBU);
*tblp = mfspr(TBR_TBL);
} while (*tbup != mfspr(TBR_TBU));
return (tb);
}
static __inline void
mttb(u_quad_t time)
{
mtspr(TBR_TBWL, 0);
mtspr(TBR_TBWU, (uint32_t)(time >> 32));
mtspr(TBR_TBWL, (uint32_t)(time & 0xffffffff));
}
static __inline void static __inline void
eieio(void) eieio(void)
{ {

View File

@ -56,11 +56,12 @@ int is_physical_memory(vm_offset_t addr);
int mem_valid(vm_offset_t addr, int len); int mem_valid(vm_offset_t addr, int len);
void decr_init(void); void decr_init(void);
void decr_ap_init(void);
void decr_tc_init(void); void decr_tc_init(void);
void cpu_setup(u_int); void cpu_setup(u_int);
struct trapframe; struct trapframe;
void powerpc_interrupt(struct trapframe *); void powerpc_interrupt(struct trapframe *);
#endif /* !_MACHINE_MD_VAR_H_ */ #endif /* !_MACHINE_MD_VAR_H_ */

View File

@ -129,8 +129,6 @@
#define SPR_SPRG7 0x117 /* 4.. SPR General 7 */ #define SPR_SPRG7 0x117 /* 4.. SPR General 7 */
#define SPR_ASR 0x118 /* ... Address Space Register (PPC64) */ #define SPR_ASR 0x118 /* ... Address Space Register (PPC64) */
#define SPR_EAR 0x11a /* .68 External Access Register */ #define SPR_EAR 0x11a /* .68 External Access Register */
#define SPR_TBL 0x11c /* 468 Time Base Lower */
#define SPR_TBU 0x11d /* 468 Time Base Upper */
#define SPR_PVR 0x11f /* 468 Processor Version Register */ #define SPR_PVR 0x11f /* 468 Processor Version Register */
#define MPC601 0x0001 #define MPC601 0x0001
#define MPC603 0x0003 #define MPC603 0x0003

View File

@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/bus.h> #include <sys/bus.h>
#include <sys/pcpu.h> #include <sys/pcpu.h>
#include <sys/proc.h> #include <sys/proc.h>
@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h> #include <machine/cpu.h>
#include <machine/intr_machdep.h> #include <machine/intr_machdep.h>
#include <machine/platform.h> #include <machine/platform.h>
#include <machine/md_var.h>
#include <machine/smp.h> #include <machine/smp.h>
#include "pic_if.h" #include "pic_if.h"
@ -47,30 +49,35 @@ __FBSDID("$FreeBSD$");
extern struct pcpu __pcpu[MAXCPU]; extern struct pcpu __pcpu[MAXCPU];
volatile static int ap_awake; volatile static int ap_awake;
volatile static u_int ap_state; volatile static u_int ap_letgo;
volatile static uint32_t ap_decr; volatile static uint32_t ap_decr;
volatile static uint32_t ap_tbl; volatile static u_quad_t ap_timebase;
static u_int ipi_msg_cnt[32];
void void
machdep_ap_bootstrap(void) machdep_ap_bootstrap(void)
{ {
pcpup->pc_awake = 1; PCPU_SET(pir, mfspr(SPR_PIR));
PCPU_SET(awake, 1);
__asm __volatile("msync; isync");
while (ap_state == 0) while (ap_letgo == 0)
; ;
mtspr(SPR_TBL, 0); /* Initialize DEC and TB, sync with the BSP values */
mtspr(SPR_TBU, 0); decr_ap_init();
mtspr(SPR_TBL, ap_tbl); mttb(ap_timebase);
__asm __volatile("mtdec %0" :: "r"(ap_decr)); __asm __volatile("mtdec %0" :: "r"(ap_decr));
ap_awake++; atomic_add_int(&ap_awake, 1);
CTR1(KTR_SMP, "SMP: AP CPU%d launched", PCPU_GET(cpuid));
/* Initialize curthread. */ /* Initialize curthread */
PCPU_SET(curthread, PCPU_GET(idlethread)); PCPU_SET(curthread, PCPU_GET(idlethread));
PCPU_SET(curpcb, curthread->td_pcb); PCPU_SET(curpcb, curthread->td_pcb);
/* Let the DEC and external interrupts go */
mtmsr(mfmsr() | PSL_EE); mtmsr(mfmsr() | PSL_EE);
sched_throw(NULL); sched_throw(NULL);
} }
@ -149,8 +156,7 @@ cpu_mp_start(void)
pc->pc_cpumask = 1 << pc->pc_cpuid; pc->pc_cpumask = 1 << pc->pc_cpuid;
pc->pc_hwref = cpu.cr_hwref; pc->pc_hwref = cpu.cr_hwref;
all_cpus |= pc->pc_cpumask; all_cpus |= pc->pc_cpumask;
next:
next:
error = platform_smp_next_cpu(&cpu); error = platform_smp_next_cpu(&cpu);
} }
} }
@ -176,7 +182,7 @@ static void
cpu_mp_unleash(void *dummy) cpu_mp_unleash(void *dummy)
{ {
struct pcpu *pc; struct pcpu *pc;
int cpus; int cpus, timeout;
if (mp_ncpus <= 1) if (mp_ncpus <= 1)
return; return;
@ -187,35 +193,47 @@ cpu_mp_unleash(void *dummy)
cpus++; cpus++;
pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask; pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
if (!pc->pc_bsp) { if (!pc->pc_bsp) {
printf("Waking up CPU %d (dev=%x)\n", pc->pc_cpuid, if (bootverbose)
pc->pc_hwref); printf("Waking up CPU %d (dev=%x)\n",
pc->pc_cpuid, pc->pc_hwref);
platform_smp_start_cpu(pc); platform_smp_start_cpu(pc);
timeout = 2000; /* wait 2sec for the AP */
while (!pc->pc_awake && --timeout > 0)
DELAY(1000);
} else { } else {
__asm __volatile("mfspr %0,1023" : "=r"(pc->pc_pir)); PCPU_SET(pir, mfspr(SPR_PIR));
pc->pc_awake = 1; pc->pc_awake = 1;
} }
if (pc->pc_awake) if (pc->pc_awake) {
if (bootverbose)
printf("Adding CPU %d, pir=%x, awake=%x\n",
pc->pc_cpuid, pc->pc_pir, pc->pc_awake);
smp_cpus++; smp_cpus++;
} else
stopped_cpus |= (1 << pc->pc_cpuid);
} }
ap_awake = 1; ap_awake = 1;
__asm __volatile("mftb %0" : "=r"(ap_tbl)); /* Provide our current DEC and TB values for APs */
ap_tbl += 10;
__asm __volatile("mfdec %0" : "=r"(ap_decr)); __asm __volatile("mfdec %0" : "=r"(ap_decr));
ap_state++; ap_timebase = mftb() + 10;
powerpc_sync(); __asm __volatile("msync; isync");
mtspr(SPR_TBL, 0); /* Let APs continue */
mtspr(SPR_TBU, 0); atomic_store_rel_int(&ap_letgo, 1);
mtspr(SPR_TBL, ap_tbl);
mttb(ap_timebase);
while (ap_awake < smp_cpus) while (ap_awake < smp_cpus)
; ;
if (smp_cpus != cpus || cpus != mp_ncpus) { if (smp_cpus != cpus || cpus != mp_ncpus) {
printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n", printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n",
mp_ncpus, cpus, smp_cpus); mp_ncpus, cpus, smp_cpus);
} }
smp_active = 1; smp_active = 1;
@ -224,8 +242,6 @@ cpu_mp_unleash(void *dummy)
SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL); SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
static u_int ipi_msg_cnt[32];
int int
powerpc_ipi_handler(void *arg) powerpc_ipi_handler(void *arg)
{ {