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:
parent
95b0b37cfc
commit
7ad9c533ef
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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_ */
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user