Unbreak non-SMP builds. This was broken by r259284. Also, reorganize the

code introduced in that revision a bit.

Reviewed by:	nwhitehorn
MFC after:	3 weeks
This commit is contained in:
jhibbits 2014-01-31 03:55:34 +00:00
parent abe2ab2c7c
commit b57e260317
13 changed files with 237 additions and 207 deletions

View File

@ -93,7 +93,7 @@ powerpc/aim/mmu_oea.c optional aim powerpc
powerpc/aim/mmu_oea64.c optional aim
powerpc/aim/moea64_if.m optional aim
powerpc/aim/moea64_native.c optional aim
powerpc/aim/mp_cpudep.c optional aim smp
powerpc/aim/mp_cpudep.c optional aim
powerpc/aim/slb.c optional aim powerpc64
powerpc/aim/trap.c optional aim
powerpc/aim/uma_machdep.c optional aim

View File

@ -142,6 +142,8 @@ int cacheline_size = 32;
#endif
int hw_direct_map = 1;
extern void *ap_pcpu;
struct pcpu __pcpu[MAXCPU];
static struct trapframe frame0;
@ -235,9 +237,7 @@ extern void *rfid_patch, *rfi_patch1, *rfi_patch2;
extern void *trapcode64;
#endif
#ifdef SMP
extern void *rstcode, *rstsize;
#endif
extern void *trapcode, *trapsize;
extern void *slbtrap, *slbtrapsize;
extern void *alitrap, *alisize;
@ -491,11 +491,7 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
generictrap = &trapcode;
#endif
#ifdef SMP
bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstsize);
#else
bcopy(generictrap, (void *)EXC_RST, (size_t)&trapsize);
#endif
#ifdef KDB
bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbsize);
@ -786,3 +782,171 @@ pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
return (pa);
}
/* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */
void
flush_disable_caches(void)
{
register_t msr;
register_t msscr0;
register_t cache_reg;
volatile uint32_t *memp;
uint32_t temp;
int i;
int x;
msr = mfmsr();
powerpc_sync();
mtmsr(msr & ~(PSL_EE | PSL_DR));
msscr0 = mfspr(SPR_MSSCR0);
msscr0 &= ~MSSCR0_L2PFE;
mtspr(SPR_MSSCR0, msscr0);
powerpc_sync();
isync();
__asm__ __volatile__("dssall; sync");
powerpc_sync();
isync();
__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
/* Lock the L1 Data cache. */
mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF);
powerpc_sync();
isync();
mtspr(SPR_LDSTCR, 0);
/*
* Perform this in two stages: Flush the cache starting in RAM, then do it
* from ROM.
*/
memp = (volatile uint32_t *)0x00000000;
for (i = 0; i < 128 * 1024; i++) {
temp = *memp;
__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
memp += 32/sizeof(*memp);
}
memp = (volatile uint32_t *)0xfff00000;
x = 0xfe;
for (; x != 0xff;) {
mtspr(SPR_LDSTCR, x);
for (i = 0; i < 128; i++) {
temp = *memp;
__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
memp += 32/sizeof(*memp);
}
x = ((x << 1) | 1) & 0xff;
}
mtspr(SPR_LDSTCR, 0);
cache_reg = mfspr(SPR_L2CR);
if (cache_reg & L2CR_L2E) {
cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450);
mtspr(SPR_L2CR, cache_reg);
powerpc_sync();
mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF);
while (mfspr(SPR_L2CR) & L2CR_L2HWF)
; /* Busy wait for cache to flush */
powerpc_sync();
cache_reg &= ~L2CR_L2E;
mtspr(SPR_L2CR, cache_reg);
powerpc_sync();
mtspr(SPR_L2CR, cache_reg | L2CR_L2I);
powerpc_sync();
while (mfspr(SPR_L2CR) & L2CR_L2I)
; /* Busy wait for L2 cache invalidate */
powerpc_sync();
}
cache_reg = mfspr(SPR_L3CR);
if (cache_reg & L3CR_L3E) {
cache_reg &= ~(L3CR_L3IO | L3CR_L3DO);
mtspr(SPR_L3CR, cache_reg);
powerpc_sync();
mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF);
while (mfspr(SPR_L3CR) & L3CR_L3HWF)
; /* Busy wait for cache to flush */
powerpc_sync();
cache_reg &= ~L3CR_L3E;
mtspr(SPR_L3CR, cache_reg);
powerpc_sync();
mtspr(SPR_L3CR, cache_reg | L3CR_L3I);
powerpc_sync();
while (mfspr(SPR_L3CR) & L3CR_L3I)
; /* Busy wait for L3 cache invalidate */
powerpc_sync();
}
mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE);
powerpc_sync();
isync();
mtmsr(msr);
}
void
cpu_sleep()
{
static u_quad_t timebase = 0;
static register_t sprgs[4];
static register_t srrs[2];
jmp_buf resetjb;
struct thread *fputd;
struct thread *vectd;
register_t hid0;
register_t msr;
register_t saved_msr;
ap_pcpu = pcpup;
PCPU_SET(restore, &resetjb);
saved_msr = mfmsr();
fputd = PCPU_GET(fputhread);
vectd = PCPU_GET(vecthread);
if (fputd != NULL)
save_fpu(fputd);
if (vectd != NULL)
save_vec(vectd);
if (setjmp(resetjb) == 0) {
sprgs[0] = mfspr(SPR_SPRG0);
sprgs[1] = mfspr(SPR_SPRG1);
sprgs[2] = mfspr(SPR_SPRG2);
sprgs[3] = mfspr(SPR_SPRG3);
srrs[0] = mfspr(SPR_SRR0);
srrs[1] = mfspr(SPR_SRR1);
timebase = mftb();
powerpc_sync();
flush_disable_caches();
hid0 = mfspr(SPR_HID0);
hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP;
powerpc_sync();
isync();
msr = mfmsr() | PSL_POW;
mtspr(SPR_HID0, hid0);
powerpc_sync();
while (1)
mtmsr(msr);
}
mttb(timebase);
PCPU_SET(curthread, curthread);
PCPU_SET(curpcb, curthread->td_pcb);
pmap_activate(curthread);
powerpc_sync();
mtspr(SPR_SPRG0, sprgs[0]);
mtspr(SPR_SPRG1, sprgs[1]);
mtspr(SPR_SPRG2, sprgs[2]);
mtspr(SPR_SPRG3, sprgs[3]);
mtspr(SPR_SRR0, srrs[0]);
mtspr(SPR_SRR1, srrs[1]);
mtmsr(saved_msr);
if (fputd == curthread)
enable_fpu(curthread);
if (vectd == curthread)
enable_vec(curthread);
powerpc_sync();
}

View File

@ -273,6 +273,14 @@ 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
switch(vers) {
case IBM970:
case IBM970FX:

View File

@ -292,7 +292,6 @@ CNAME(restorebridge):
isync
CNAME(restorebridgesize) = .-CNAME(restorebridge)
#ifdef SMP
/*
* Processor reset exception handler. These are typically
* the first instructions the processor executes after a
@ -320,12 +319,21 @@ cpu_reset:
bla CNAME(pmap_cpu_bootstrap)
bla CNAME(cpudep_ap_bootstrap)
mr %r1,%r3
bla CNAME(cpudep_ap_setup)
GET_CPUINFO(%r5)
lwz %r3,(PC_RESTORE)(%r5)
cmplwi %cr0,%r3,0
beq %cr0,2f
li %r4, 1
b CNAME(longjmp)
2:
#ifdef SMP
bla CNAME(machdep_ap_bootstrap)
#endif
/* Should not be reached */
9:
b 9b
#endif
/*
* This code gets copied to all the trap vectors

View File

@ -287,7 +287,6 @@ dtrace_invop_calltrap_addr:
.text
#endif
#ifdef SMP
/*
* Processor reset exception handler. These are typically
* the first instructions the processor executes after a
@ -322,13 +321,25 @@ cpu_reset:
bl CNAME(cpudep_ap_bootstrap) /* Set up PCPU and stack */
nop
mr %r1,%r3 /* Use new stack */
bl CNAME(cpudep_ap_setup)
nop
GET_CPUINFO(%r5)
ld %r3,(PC_RESTORE)(%r5)
cmpldi %cr0,%r3,0
beq %cr0,2f
nop
li %r4,1
b CNAME(longjmp)
nop
2:
#ifdef SMP
bl CNAME(machdep_ap_bootstrap) /* And away! */
nop
#endif
/* Should not be reached */
9:
b 9b
#endif
/*
* This code gets copied to all the trap vectors

View File

@ -95,9 +95,9 @@ extern char etext[];
void cpu_halt(void);
void cpu_reset(void);
void cpu_sleep(void);
void flush_disable_caches(void);
void fork_trampoline(void);
void swi_vm(void *);
void flush_disable_caches(void);
#endif /* _MACHINE_CPU_H_ */

View File

@ -56,5 +56,7 @@ void platform_smp_ap_init(void);
const char *installed_platform(void);
void platform_probe_and_attach(void);
void platform_sleep(void);
#endif /* _MACHINE_PLATFORM_H_ */

View File

@ -38,11 +38,14 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/altivec.h> /* For save_vec() */
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/fpu.h> /* For save_fpu() */
#include <machine/hid.h>
#include <machine/platformvar.h>
#include <machine/pmap.h>
#include <machine/setjmp.h>
#include <machine/smp.h>
#include <machine/spr.h>
@ -51,9 +54,7 @@ __FBSDID("$FreeBSD$");
#include "platform_if.h"
#ifdef SMP
extern void *ap_pcpu;
#endif
static int powermac_probe(platform_t);
static int powermac_attach(platform_t);
@ -65,6 +66,7 @@ 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_reset(platform_t);
static void powermac_sleep(platform_t);
static platform_method_t powermac_methods[] = {
PLATFORMMETHOD(platform_probe, powermac_probe),
@ -78,6 +80,7 @@ static platform_method_t powermac_methods[] = {
PLATFORMMETHOD(platform_smp_start_cpu, powermac_smp_start_cpu),
PLATFORMMETHOD(platform_reset, powermac_reset),
PLATFORMMETHOD(platform_sleep, powermac_sleep),
PLATFORMMETHOD_END
};
@ -376,113 +379,17 @@ powermac_smp_start_cpu(platform_t plat, struct pcpu *pc)
#endif
}
/* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */
void
flush_disable_caches(void)
{
register_t msr;
register_t msscr0;
register_t cache_reg;
volatile uint32_t *memp;
uint32_t temp;
int i;
int x;
msr = mfmsr();
powerpc_sync();
mtmsr(msr & ~(PSL_EE | PSL_DR));
msscr0 = mfspr(SPR_MSSCR0);
msscr0 &= ~MSSCR0_L2PFE;
mtspr(SPR_MSSCR0, msscr0);
powerpc_sync();
isync();
__asm__ __volatile__("dssall; sync");
powerpc_sync();
isync();
__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
/* Lock the L1 Data cache. */
mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF);
powerpc_sync();
isync();
mtspr(SPR_LDSTCR, 0);
/*
* Perform this in two stages: Flush the cache starting in RAM, then do it
* from ROM.
*/
memp = (volatile uint32_t *)0x00000000;
for (i = 0; i < 128 * 1024; i++) {
temp = *memp;
__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
memp += 32/sizeof(*memp);
}
memp = (volatile uint32_t *)0xfff00000;
x = 0xfe;
for (; x != 0xff;) {
mtspr(SPR_LDSTCR, x);
for (i = 0; i < 128; i++) {
temp = *memp;
__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
memp += 32/sizeof(*memp);
}
x = ((x << 1) | 1) & 0xff;
}
mtspr(SPR_LDSTCR, 0);
cache_reg = mfspr(SPR_L2CR);
if (cache_reg & L2CR_L2E) {
cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450);
mtspr(SPR_L2CR, cache_reg);
powerpc_sync();
mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF);
while (mfspr(SPR_L2CR) & L2CR_L2HWF)
; /* Busy wait for cache to flush */
powerpc_sync();
cache_reg &= ~L2CR_L2E;
mtspr(SPR_L2CR, cache_reg);
powerpc_sync();
mtspr(SPR_L2CR, cache_reg | L2CR_L2I);
powerpc_sync();
while (mfspr(SPR_L2CR) & L2CR_L2I)
; /* Busy wait for L2 cache invalidate */
powerpc_sync();
}
cache_reg = mfspr(SPR_L3CR);
if (cache_reg & L3CR_L3E) {
cache_reg &= ~(L3CR_L3IO | L3CR_L3DO);
mtspr(SPR_L3CR, cache_reg);
powerpc_sync();
mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF);
while (mfspr(SPR_L3CR) & L3CR_L3HWF)
; /* Busy wait for cache to flush */
powerpc_sync();
cache_reg &= ~L3CR_L3E;
mtspr(SPR_L3CR, cache_reg);
powerpc_sync();
mtspr(SPR_L3CR, cache_reg | L3CR_L3I);
powerpc_sync();
while (mfspr(SPR_L3CR) & L3CR_L3I)
; /* Busy wait for L3 cache invalidate */
powerpc_sync();
}
mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE);
powerpc_sync();
isync();
mtmsr(msr);
}
static void
powermac_reset(platform_t platform)
{
OF_reboot();
}
void
powermac_sleep(platform_t platform)
{
*(unsigned long *)0x80 = 0x100;
cpu_sleep();
}

View File

@ -45,17 +45,14 @@ __FBSDID("$FreeBSD$");
#include <dev/led/led.h>
#include <machine/_inttypes.h>
#include <machine/altivec.h> /* For save_vec() */
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/fpu.h> /* For save_fpu() */
#include <machine/hid.h>
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/pio.h>
#include <machine/resource.h>
#include <machine/setjmp.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@ -106,7 +103,6 @@ static int pmu_acline_state(SYSCTL_HANDLER_ARGS);
static int pmu_query_battery(struct pmu_softc *sc, int batt,
struct pmu_battstate *info);
static int pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS);
static void pmu_sleep_int(void);
/*
* List of battery-related sysctls we might ask for
@ -1031,72 +1027,6 @@ pmu_settime(device_t dev, struct timespec *ts)
return (0);
}
static register_t sprgs[4];
static register_t srrs[2];
extern void *ap_pcpu;
void pmu_sleep_int(void)
{
static u_quad_t timebase = 0;
jmp_buf resetjb;
struct thread *fputd;
struct thread *vectd;
register_t hid0;
register_t msr;
register_t saved_msr;
ap_pcpu = pcpup;
PCPU_SET(restore, &resetjb);
*(unsigned long *)0x80 = 0x100;
saved_msr = mfmsr();
fputd = PCPU_GET(fputhread);
vectd = PCPU_GET(vecthread);
if (fputd != NULL)
save_fpu(fputd);
if (vectd != NULL)
save_vec(vectd);
if (setjmp(resetjb) == 0) {
sprgs[0] = mfspr(SPR_SPRG0);
sprgs[1] = mfspr(SPR_SPRG1);
sprgs[2] = mfspr(SPR_SPRG2);
sprgs[3] = mfspr(SPR_SPRG3);
srrs[0] = mfspr(SPR_SRR0);
srrs[1] = mfspr(SPR_SRR1);
timebase = mftb();
powerpc_sync();
flush_disable_caches();
hid0 = mfspr(SPR_HID0);
hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP;
powerpc_sync();
isync();
msr = mfmsr() | PSL_POW;
mtspr(SPR_HID0, hid0);
powerpc_sync();
while (1)
mtmsr(msr);
}
mttb(timebase);
PCPU_SET(curthread, curthread);
PCPU_SET(curpcb, curthread->td_pcb);
pmap_activate(curthread);
powerpc_sync();
mtspr(SPR_SPRG0, sprgs[0]);
mtspr(SPR_SPRG1, sprgs[1]);
mtspr(SPR_SPRG2, sprgs[2]);
mtspr(SPR_SPRG3, sprgs[3]);
mtspr(SPR_SRR0, srrs[0]);
mtspr(SPR_SRR1, srrs[1]);
mtmsr(saved_msr);
if (fputd == curthread)
enable_fpu(curthread);
if (vectd == curthread)
enable_vec(curthread);
powerpc_sync();
}
int
pmu_set_speed(int low_speed)
{
@ -1114,7 +1044,7 @@ pmu_set_speed(int low_speed)
sleepcmd[4] = low_speed;
pmu_send(sc, PMU_CPU_SPEED, 5, sleepcmd, 16, resp);
unin_chip_sleep(NULL, 1);
pmu_sleep_int();
platform_sleep();
unin_chip_wake(NULL);
mtdec(1); /* Force a decrementer exception */

View File

@ -62,6 +62,7 @@ ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
ASSYM(PC_TEMPSAVE, offsetof(struct pcpu, pc_tempsave));
ASSYM(PC_DISISAVE, offsetof(struct pcpu, pc_disisave));
ASSYM(PC_DBSAVE, offsetof(struct pcpu, pc_dbsave));
ASSYM(PC_RESTORE, offsetof(struct pcpu, pc_restore));
#if defined(BOOKE)
ASSYM(PC_BOOKE_CRITSAVE, offsetof(struct pcpu, pc_booke_critsave));

View File

@ -72,29 +72,12 @@ int longfault(faultbuf, int);
void
machdep_ap_bootstrap(void)
{
jmp_buf *restore;
/* 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
/* Set up important bits on the CPU (HID registers, etc.) */
cpudep_ap_setup();
/* Set PIR */
PCPU_SET(pir, mfspr(SPR_PIR));
PCPU_SET(awake, 1);
__asm __volatile("msync; isync");
restore = PCPU_GET(restore);
if (restore != NULL) {
longjmp(*restore, 1);
}
while (ap_letgo == 0)
;

View File

@ -196,6 +196,15 @@ platform_timebase_freq(struct cpuref *cpu)
return (PLATFORM_TIMEBASE_FREQ(plat_obj, cpu));
}
/*
* Put the current CPU, as last step in suspend, to sleep
*/
void
platform_sleep()
{
PLATFORM_SLEEP(plat_obj);
}
int
platform_smp_first_cpu(struct cpuref *cpu)
{

View File

@ -210,3 +210,10 @@ METHOD void reset {
platform_t _plat;
};
/**
* @brief Suspend the CPU
*/
METHOD void sleep {
platform_t _plat;
};