summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-11-12 03:43:22 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-11-12 03:43:22 +0000
commitb60b3b77532b00e2d6d085b6d2cf1c55a94d6690 (patch)
treed7c7eab3713ec62c4130904b95aba146f88cc89f /sys/powerpc
parent95c949e611a9c4de7cef2b654936b673a6c23ca9 (diff)
downloadFreeBSD-src-b60b3b77532b00e2d6d085b6d2cf1c55a94d6690.zip
FreeBSD-src-b60b3b77532b00e2d6d085b6d2cf1c55a94d6690.tar.gz
Centralize CPU idle routines into powerpc/cpu.c and use the same
cpu_idle_hook mechanism that x86 uses for overriding the idle routine. This is required for supporting ilding the CPU under PowerPC hypervisors.
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/aim/machdep.c58
-rw-r--r--sys/powerpc/booke/machdep.c44
-rw-r--r--sys/powerpc/powerpc/cpu.c100
3 files changed, 98 insertions, 104 deletions
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index f52f7a4..456fa44 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -639,64 +639,6 @@ cpu_halt(void)
OF_exit();
}
-void
-cpu_idle(int busy)
-{
- register_t msr;
- uint16_t vers;
-
- msr = mfmsr();
- vers = mfpvr() >> 16;
-
-#ifdef INVARIANTS
- if ((msr & PSL_EE) != PSL_EE) {
- struct thread *td = curthread;
- printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr);
- panic("ints disabled in idleproc!");
- }
-#endif
- CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
- busy, curcpu);
- if (powerpc_pow_enabled) {
- if (!busy) {
- critical_enter();
- cpu_idleclock();
- }
- switch (vers) {
- case IBM970:
- case IBM970FX:
- case IBM970MP:
- case MPC7447A:
- case MPC7448:
- case MPC7450:
- case MPC7455:
- case MPC7457:
- __asm __volatile("\
- dssall; sync; mtmsr %0; isync"
- :: "r"(msr | PSL_POW));
- break;
- default:
- powerpc_sync();
- mtmsr(msr | PSL_POW);
- isync();
- break;
- }
- if (!busy) {
- cpu_activeclock();
- critical_exit();
- }
- }
- CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
- busy, curcpu);
-}
-
-int
-cpu_idle_wakeup(int cpu)
-{
-
- return (0);
-}
-
int
ptrace_set_pc(struct thread *td, unsigned long addr)
{
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index b8a77a5..860c271 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -468,50 +468,6 @@ cpu_flush_dcache(void *ptr, size_t len)
/* TBD */
}
-/*
- * cpu_idle
- *
- * Set Wait state enable.
- */
-void
-cpu_idle (int busy)
-{
- register_t msr;
-
- msr = mfmsr();
-
-#ifdef INVARIANTS
- if ((msr & PSL_EE) != PSL_EE) {
- struct thread *td = curthread;
- printf("td msr %x\n", td->td_md.md_saved_msr);
- panic("ints disabled in idleproc!");
- }
-#endif
-
- CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
- busy, curcpu);
- if (!busy) {
- critical_enter();
- cpu_idleclock();
- }
- /* Freescale E500 core RM section 6.4.1. */
- msr = msr | PSL_WE;
- __asm __volatile("msync; mtmsr %0; isync" :: "r" (msr));
- if (!busy) {
- cpu_activeclock();
- critical_exit();
- }
- CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
- busy, curcpu);
-}
-
-int
-cpu_idle_wakeup(int cpu)
-{
-
- return (0);
-}
-
void
spinlock_enter(void)
{
diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c
index 4bbfcac..e5d43d8 100644
--- a/sys/powerpc/powerpc/cpu.c
+++ b/sys/powerpc/powerpc/cpu.c
@@ -64,6 +64,7 @@
#include <sys/conf.h>
#include <sys/cpu.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/sysctl.h>
#include <machine/bus.h>
@@ -73,12 +74,15 @@
#include <machine/smp.h>
#include <machine/spr.h>
-int powerpc_pow_enabled;
-
static void cpu_6xx_setup(int cpuid, uint16_t vers);
static void cpu_e500_setup(int cpuid, uint16_t vers);
static void cpu_970_setup(int cpuid, uint16_t vers);
+int powerpc_pow_enabled;
+void (*cpu_idle_hook)(void) = NULL;
+static void cpu_idle_60x(void);
+static void cpu_idle_e500(void);
+
struct cputab {
const char *name;
uint16_t version;
@@ -374,6 +378,9 @@ cpu_6xx_setup(int cpuid, uint16_t vers)
}
printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask);
+
+ if (cpu_idle_hook == NULL)
+ cpu_idle_hook = cpu_idle_60x;
}
@@ -441,6 +448,9 @@ cpu_e500_setup(int cpuid, uint16_t vers)
mtspr(SPR_HID0, hid0);
printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK);
+
+ if (cpu_idle_hook == NULL)
+ cpu_idle_hook = cpu_idle_e500;
}
static void
@@ -478,6 +488,8 @@ cpu_970_setup(int cpuid, uint16_t vers)
: "=r" (hid0_hi) : "K" (SPR_HID0));
printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK);
#endif
+
+ cpu_idle_hook = cpu_idle_60x;
}
static int
@@ -490,3 +502,87 @@ cpu_feature_bit(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_int(oidp, &result, 0, req));
}
+void
+cpu_idle(int busy)
+{
+
+#ifdef INVARIANTS
+ if ((mfmsr() & PSL_EE) != PSL_EE) {
+ struct thread *td = curthread;
+ printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr);
+ panic("ints disabled in idleproc!");
+ }
+#endif
+
+ CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
+ busy, curcpu);
+ if (cpu_idle_hook != NULL) {
+ if (!busy) {
+ critical_enter();
+ cpu_idleclock();
+ }
+ cpu_idle_hook();
+ if (!busy) {
+ cpu_activeclock();
+ critical_exit();
+ }
+ }
+ CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
+ busy, curcpu);
+}
+
+int
+cpu_idle_wakeup(int cpu)
+{
+ return (0);
+}
+
+static void
+cpu_idle_60x(void)
+{
+ register_t msr;
+ uint16_t vers;
+
+ if (!powerpc_pow_enabled)
+ return;
+
+ msr = mfmsr();
+ vers = mfpvr() >> 16;
+
+#ifdef AIM
+ switch (vers) {
+ case IBM970:
+ case IBM970FX:
+ case IBM970MP:
+ case MPC7447A:
+ case MPC7448:
+ case MPC7450:
+ case MPC7455:
+ case MPC7457:
+ __asm __volatile("\
+ dssall; sync; mtmsr %0; isync"
+ :: "r"(msr | PSL_POW));
+ break;
+ default:
+ powerpc_sync();
+ mtmsr(msr | PSL_POW);
+ isync();
+ break;
+ }
+#endif
+}
+
+static void
+cpu_idle_e500(void)
+{
+ register_t msr;
+
+ msr = mfmsr();
+
+#ifdef E500
+ /* Freescale E500 core RM section 6.4.1. */
+ __asm __volatile("msync; mtmsr %0; isync" ::
+ "r" (msr | PSL_WE));
+#endif
+}
+
OpenPOWER on IntegriCloud