mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
Whether you can use mttb() or not is more complicated than whether PSL_HV
is set and the right thing to do may be platform-dependent (it requires firmware on PowerNV, for instance). Make it a new platform method called platform_smp_timebase_sync(). MFC after: 3 weeks
This commit is contained in:
parent
763864aa95
commit
de2dd83fb9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=326205
|
@ -281,13 +281,8 @@ cpudep_ap_setup()
|
|||
vers = mfpvr() >> 16;
|
||||
|
||||
/* The following is needed for restoring from sleep. */
|
||||
#ifdef __powerpc64__
|
||||
/* Writing to the time base register is hypervisor-privileged */
|
||||
if (mfmsr() & PSL_HV)
|
||||
mttb(0);
|
||||
#else
|
||||
mttb(0);
|
||||
#endif
|
||||
platform_smp_timebase_sync(0, 1);
|
||||
|
||||
switch(vers) {
|
||||
case IBM970:
|
||||
case IBM970FX:
|
||||
|
|
|
@ -45,6 +45,8 @@ struct mem_region {
|
|||
uint64_t mr_size;
|
||||
};
|
||||
|
||||
/* Documentation for these functions is in platform_if.m */
|
||||
|
||||
void mem_regions(struct mem_region **, int *, struct mem_region **, int *);
|
||||
vm_offset_t platform_real_maxaddr(void);
|
||||
|
||||
|
@ -54,6 +56,7 @@ int platform_smp_first_cpu(struct cpuref *);
|
|||
int platform_smp_next_cpu(struct cpuref *);
|
||||
int platform_smp_get_bsp(struct cpuref *);
|
||||
int platform_smp_start_cpu(struct pcpu *);
|
||||
void platform_smp_timebase_sync(u_long tb, int ap);
|
||||
void platform_smp_ap_init(void);
|
||||
|
||||
const char *installed_platform(void);
|
||||
|
|
|
@ -92,6 +92,7 @@ static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref);
|
|||
static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref);
|
||||
static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref);
|
||||
static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu);
|
||||
static void mpc85xx_smp_timebase_sync(platform_t, u_long tb, int ap);
|
||||
static void mpc85xx_idle(platform_t, int cpu);
|
||||
static int mpc85xx_idle_wakeup(platform_t plat, int cpu);
|
||||
|
||||
|
@ -107,6 +108,7 @@ static platform_method_t mpc85xx_methods[] = {
|
|||
PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu),
|
||||
PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp),
|
||||
PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu),
|
||||
PLATFORMMETHOD(platform_smp_timebase_sync, mpc85xx_smp_timebase_sync),
|
||||
|
||||
PLATFORMMETHOD(platform_reset, mpc85xx_reset),
|
||||
PLATFORMMETHOD(platform_idle, mpc85xx_idle),
|
||||
|
@ -528,6 +530,13 @@ mpc85xx_reset(platform_t plat)
|
|||
;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc85xx_smp_timebase_sync(platform_t plat, u_long tb, int ap)
|
||||
{
|
||||
|
||||
mttb(tb);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc85xx_idle(platform_t plat, int cpu)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,7 @@ static int powermac_smp_first_cpu(platform_t, struct cpuref *cpuref);
|
|||
static int powermac_smp_next_cpu(platform_t, struct cpuref *cpuref);
|
||||
static int powermac_smp_get_bsp(platform_t, struct cpuref *cpuref);
|
||||
static int powermac_smp_start_cpu(platform_t, struct pcpu *cpu);
|
||||
static void powermac_smp_timebase_sync(platform_t, u_long tb, int ap);
|
||||
static void powermac_reset(platform_t);
|
||||
static void powermac_sleep(platform_t);
|
||||
|
||||
|
@ -77,6 +78,7 @@ static platform_method_t powermac_methods[] = {
|
|||
PLATFORMMETHOD(platform_smp_next_cpu, powermac_smp_next_cpu),
|
||||
PLATFORMMETHOD(platform_smp_get_bsp, powermac_smp_get_bsp),
|
||||
PLATFORMMETHOD(platform_smp_start_cpu, powermac_smp_start_cpu),
|
||||
PLATFORMMETHOD(platform_smp_timebase_sync, powermac_smp_timebase_sync),
|
||||
|
||||
PLATFORMMETHOD(platform_reset, powermac_reset),
|
||||
PLATFORMMETHOD(platform_sleep, powermac_sleep),
|
||||
|
@ -389,6 +391,13 @@ powermac_smp_start_cpu(platform_t plat, struct pcpu *pc)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
powermac_smp_timebase_sync(platform_t plat, u_long tb, int ap)
|
||||
{
|
||||
|
||||
mttb(tb);
|
||||
}
|
||||
|
||||
static void
|
||||
powermac_reset(platform_t platform)
|
||||
{
|
||||
|
|
|
@ -81,13 +81,7 @@ machdep_ap_bootstrap(void)
|
|||
;
|
||||
|
||||
/* Initialize DEC and TB, sync with the BSP values */
|
||||
#ifdef __powerpc64__
|
||||
/* Writing to the time base register is hypervisor-privileged */
|
||||
if (mfmsr() & PSL_HV)
|
||||
mttb(ap_timebase);
|
||||
#else
|
||||
mttb(ap_timebase);
|
||||
#endif
|
||||
platform_smp_timebase_sync(ap_timebase, 1);
|
||||
decr_ap_init();
|
||||
|
||||
/* Give platform code a chance to do anything necessary */
|
||||
|
@ -144,7 +138,6 @@ cpu_mp_start(void)
|
|||
|
||||
error = platform_smp_get_bsp(&bsp);
|
||||
KASSERT(error == 0, ("Don't know BSP"));
|
||||
KASSERT(bsp.cr_cpuid == 0, ("%s: cpuid != 0", __func__));
|
||||
|
||||
error = platform_smp_first_cpu(&cpu);
|
||||
while (!error) {
|
||||
|
@ -184,7 +177,7 @@ cpu_mp_announce(void)
|
|||
struct pcpu *pc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= mp_maxid; i++) {
|
||||
CPU_FOREACH(i) {
|
||||
pc = pcpu_find(i);
|
||||
if (pc == NULL)
|
||||
continue;
|
||||
|
@ -246,13 +239,7 @@ cpu_mp_unleash(void *dummy)
|
|||
/* Let APs continue */
|
||||
atomic_store_rel_int(&ap_letgo, 1);
|
||||
|
||||
#ifdef __powerpc64__
|
||||
/* Writing to the time base register is hypervisor-privileged */
|
||||
if (mfmsr() & PSL_HV)
|
||||
mttb(ap_timebase);
|
||||
#else
|
||||
mttb(ap_timebase);
|
||||
#endif
|
||||
platform_smp_timebase_sync(ap_timebase, 0);
|
||||
|
||||
while (ap_awake < smp_cpus)
|
||||
;
|
||||
|
|
|
@ -266,6 +266,12 @@ platform_cpu_idle(int cpu)
|
|||
PLATFORM_IDLE(plat_obj, cpu);
|
||||
}
|
||||
|
||||
void platform_smp_timebase_sync(u_long tb, int ap)
|
||||
{
|
||||
|
||||
PLATFORM_SMP_TIMEBASE_SYNC(plat_obj, tb, ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Platform install routines. Highest priority wins, using the same
|
||||
* algorithm as bus attachment.
|
||||
|
|
|
@ -241,3 +241,14 @@ METHOD void sleep {
|
|||
platform_t _plat;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attempt to synchronize timebase of current CPU with others.
|
||||
* Entered (approximately) simultaneously on all CPUs, including the BSP.
|
||||
* Passed the timebase value on the BSP as of shortly before the call.
|
||||
*/
|
||||
METHOD void smp_timebase_sync {
|
||||
platform_t _plat;
|
||||
u_long _tb;
|
||||
int _ap;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue