summaryrefslogtreecommitdiffstats
path: root/core/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/cpu.c')
-rw-r--r--core/cpu.c60
1 files changed, 49 insertions, 11 deletions
diff --git a/core/cpu.c b/core/cpu.c
index a03cf916..c4a4d29e 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -286,14 +286,10 @@ void cpu_process_jobs(void)
unlock(&cpu->job_lock);
}
-static void cpu_idle_default(enum cpu_wake_cause wake_on __unused)
-{
- /* Maybe do something better for simulators ? */
- cpu_relax();
- cpu_relax();
- cpu_relax();
- cpu_relax();
-}
+enum cpu_wake_cause {
+ cpu_wake_on_job,
+ cpu_wake_on_dec,
+};
static void cpu_idle_p8(enum cpu_wake_cause wake_on)
{
@@ -301,7 +297,7 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on)
struct cpu_thread *cpu = this_cpu();
if (!pm_enabled) {
- cpu_idle_default(wake_on);
+ prlog_once(PR_DEBUG, "cpu_idle_p8 called pm disabled\n");
return;
}
@@ -373,18 +369,60 @@ void cpu_set_pm_enable(bool enabled)
}
}
-void cpu_idle(enum cpu_wake_cause wake_on)
+static void cpu_idle_pm(enum cpu_wake_cause wake_on)
{
switch(proc_gen) {
case proc_gen_p8:
cpu_idle_p8(wake_on);
break;
default:
- cpu_idle_default(wake_on);
+ prlog_once(PR_DEBUG, "cpu_idle_pm called with bad processor type\n");
break;
}
}
+void cpu_idle_job(void)
+{
+ if (pm_enabled) {
+ cpu_idle_pm(cpu_wake_on_job);
+ } else {
+ struct cpu_thread *cpu = this_cpu();
+
+ smt_lowest();
+ /* Check for jobs again */
+ while (!cpu_check_jobs(cpu))
+ barrier();
+ smt_medium();
+ }
+}
+
+void cpu_idle_delay(unsigned long delay, unsigned long min_pm)
+{
+ unsigned long now = mftb();
+ unsigned long end = now + delay;
+
+ if (pm_enabled && delay > min_pm) {
+ for (;;) {
+ if (delay >= 0x7fffffff)
+ delay = 0x7fffffff;
+ mtspr(SPR_DEC, delay);
+
+ cpu_idle_pm(cpu_wake_on_dec);
+
+ now = mftb();
+ if (tb_compare(now, end) == TB_AAFTERB)
+ break;
+
+ delay = end - now;
+ }
+ } else {
+ smt_lowest();
+ while (tb_compare(mftb(), end) != TB_AAFTERB)
+ barrier();
+ smt_medium();
+ }
+}
+
void cpu_process_local_jobs(void)
{
struct cpu_thread *cpu = first_available_cpu();
OpenPOWER on IntegriCloud