xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: "Jan Beulich" <JBeulich@suse.com>
To: xen-devel <xen-devel@lists.xenproject.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: [PATCH 3/5] x86/cpuidle: push parked CPUs into deeper sleep states when possible
Date: Wed, 01 Aug 2018 08:32:29 -0600	[thread overview]
Message-ID: <5B61C47D02000078001D9F65@prv1-mh.provo.novell.com> (raw)
In-Reply-To: <5B61C21202000078001D9F2D@prv1-mh.provo.novell.com>

When the mwait-idle driver isn't used, C-state information becomes
available only in the course of Dom0 starting up. Use the provided data
to allow parked CPUs to sleep in a more energy efficient way, by waking
them briefly (via NMI) once the data has been recorded.

This involves re-arranging how/when the governor's ->enable() hook gets
invoked. The changes there include addition of so far missing error
handling in the respective CPU notifier handlers.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -351,12 +351,22 @@ static void dump_cx(unsigned char key)
     unsigned int cpu;
 
     printk("'%c' pressed -> printing ACPI Cx structures\n", key);
-    for_each_online_cpu ( cpu )
-        if (processor_powers[cpu])
-        {
-            print_acpi_power(cpu, processor_powers[cpu]);
-            process_pending_softirqs();
-        }
+    for_each_present_cpu ( cpu )
+    {
+        struct acpi_processor_power *power = processor_powers[cpu];
+
+        if ( !power )
+            continue;
+
+        if ( cpu_online(cpu) )
+            print_acpi_power(cpu, power);
+        else if ( park_offline_cpus )
+            printk("CPU%u parked in state %u (C%u)\n", cpu,
+                   power->last_state ? power->last_state->idx : 1,
+                   power->last_state ? power->last_state->type : 1);
+
+        process_pending_softirqs();
+    }
 }
 
 static int __init cpu_idle_key_init(void)
@@ -764,6 +774,7 @@ void acpi_dead_idle(void)
         goto default_halt;
 
     cx = &power->states[power->count - 1];
+    power->last_state = cx;
 
     if ( cx->entry_method == ACPI_CSTATE_EM_FFH )
     {
@@ -1216,9 +1227,30 @@ long set_cx_pminfo(uint32_t acpi_id, str
         set_cx(acpi_power, &xen_cx);
     }
 
-    if ( cpuidle_current_governor->enable &&
-         cpuidle_current_governor->enable(acpi_power) )
-        return -EFAULT;
+    if ( !cpu_online(cpu_id) )
+    {
+        uint32_t apic_id = x86_cpu_to_apicid[cpu_id];
+
+        /*
+         * If we've just learned of more available C states, wake the CPU if
+         * it's parked, so it can go back to sleep in perhaps a deeper state.
+         */
+        if ( park_offline_cpus && apic_id != BAD_APICID )
+        {
+            unsigned long flags;
+
+            local_irq_save(flags);
+            apic_wait_icr_idle();
+            apic_icr_write(APIC_DM_NMI | APIC_DEST_PHYSICAL, apic_id);
+            local_irq_restore(flags);
+        }
+    }
+    else if ( cpuidle_current_governor->enable )
+    {
+        ret = cpuidle_current_governor->enable(acpi_power);
+        if ( ret < 0 )
+            return ret;
+    }
 
     /* FIXME: C-state dependency is not supported by far */
 
@@ -1378,19 +1410,22 @@ static int cpu_callback(
     struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
     unsigned int cpu = (unsigned long)hcpu;
+    int rc = 0;
 
-    /* Only hook on CPU_ONLINE because a dead cpu may utilize the info to
-     * to enter deep C-state */
+    /*
+     * Only hook on CPU_UP_PREPARE because a dead cpu may utilize the info
+     * to enter deep C-state.
+     */
     switch ( action )
     {
-    case CPU_ONLINE:
-        (void)cpuidle_init_cpu(cpu);
-        break;
-    default:
+    case CPU_UP_PREPARE:
+        rc = cpuidle_init_cpu(cpu);
+        if ( !rc && cpuidle_current_governor->enable )
+            rc = cpuidle_current_governor->enable(processor_powers[cpu]);
         break;
     }
 
-    return NOTIFY_DONE;
+    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
 }
 
 static struct notifier_block cpu_nfb = {
@@ -1405,6 +1440,7 @@ static int __init cpuidle_presmp_init(vo
         return 0;
 
     mwait_idle_init(&cpu_nfb);
+    cpu_nfb.notifier_call(&cpu_nfb, CPU_UP_PREPARE, cpu);
     cpu_nfb.notifier_call(&cpu_nfb, CPU_ONLINE, cpu);
     register_cpu_notifier(&cpu_nfb);
     return 0;
--- a/xen/arch/x86/acpi/cpuidle_menu.c
+++ b/xen/arch/x86/acpi/cpuidle_menu.c
@@ -277,9 +277,6 @@ static void menu_reflect(struct acpi_pro
 
 static int menu_enable_device(struct acpi_processor_power *power)
 {
-    if (!cpu_online(power->cpu))
-        return -1;
-
     memset(&per_cpu(menu_devices, power->cpu), 0, sizeof(struct menu_device));
 
     return 0;
--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -1162,12 +1162,17 @@ static int mwait_idle_cpu_init(struct no
 	struct acpi_processor_power *dev = processor_powers[cpu];
 
 	switch (action) {
+		int rc;
+
 	default:
 		return NOTIFY_DONE;
 
 	case CPU_UP_PREPARE:
-		cpuidle_init_cpu(cpu);
-		return NOTIFY_DONE;
+		rc = cpuidle_init_cpu(cpu);
+		dev = processor_powers[cpu];
+		if (!rc && cpuidle_current_governor->enable)
+			rc = cpuidle_current_governor->enable(dev);
+		return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
 
 	case CPU_ONLINE:
 		if (!dev)
@@ -1256,8 +1261,6 @@ int __init mwait_idle_init(struct notifi
 	}
 	if (!err) {
 		nfb->notifier_call = mwait_idle_cpu_init;
-		mwait_idle_cpu_init(nfb, CPU_UP_PREPARE, NULL);
-
 		pm_idle_save = pm_idle;
 		pm_idle = mwait_idle;
 		dead_idle = acpi_dead_idle;




_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-08-01 14:32 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-01 14:22 [PATCH 0/5] x86: more power-efficient CPU parking Jan Beulich
2018-08-01 14:31 ` [PATCH 1/5] x86/cpuidle: replace a pointless NULL check Jan Beulich
2018-08-01 14:33   ` Andrew Cooper
2018-08-01 15:12     ` Jan Beulich
2018-08-01 14:31 ` [PATCH 2/5] x86/idle: re-arrange dead-idle handling Jan Beulich
2018-09-07 17:08   ` Andrew Cooper
2018-09-10 10:13     ` Jan Beulich
2018-10-26 10:55       ` Ping: " Jan Beulich
2018-12-05 20:33       ` Andrew Cooper
2018-12-06  8:16         ` Jan Beulich
2018-08-01 14:32 ` Jan Beulich [this message]
2018-10-26 10:56   ` Ping: [PATCH 3/5] x86/cpuidle: push parked CPUs into deeper sleep states when possible Jan Beulich
2018-08-01 14:33 ` [PATCH 4/5] x86/cpuidle: clean up Cx dumping Jan Beulich
2018-08-01 14:40   ` Andrew Cooper
2018-08-01 14:33 ` [PATCH 5/5] x86: place non-parked CPUs into wait-for-SIPI state after offlining Jan Beulich
2018-08-29  7:08 ` Ping: [PATCH 0/5] x86: more power-efficient CPU parking Jan Beulich
2018-08-29 17:01   ` Andrew Cooper
2018-08-30  7:29     ` Jan Beulich
     [not found] ` <5B61C21202000000000FC1F1@prv1-mh.provo.novell.com>
     [not found]   ` <5B61C21202000078001F8805@prv1-mh.provo.novell.com>
     [not found]     ` <5B61C21202000000000FC6BD@prv1-mh.provo.novell.com>
     [not found]       ` <5B61C212020000780020B6D8@prv1-mh.provo.novell.com>
     [not found]         ` <5B61C21202000000000FF27E@prv1-mh.provo.novell.com>
     [not found]           ` <5B61C2120200007800224310@prv1-mh.provo.novell.com>
2019-04-03 10:12             ` Jan Beulich
2019-04-03 11:14               ` Andrew Cooper
2019-04-03 12:43                 ` Jan Beulich
2019-04-03 14:44                   ` Andrew Cooper
2019-04-03 15:20                     ` Jan Beulich
     [not found]             ` <5B61C2120200000000101EDC@prv1-mh.provo.novell.com>
     [not found]               ` <5B61C212020000780022FF0D@prv1-mh.provo.novell.com>
2019-05-17 10:10                 ` [PATCH v2 0/3] " Jan Beulich
2019-05-17 10:10                   ` [Xen-devel] " Jan Beulich
2019-05-17 10:11                   ` [PATCH v2 1/3] x86/idle: re-arrange dead-idle handling Jan Beulich
2019-05-17 10:11                     ` [Xen-devel] " Jan Beulich
2019-05-20 14:25                     ` Andrew Cooper
2019-05-20 14:25                       ` [Xen-devel] " Andrew Cooper
2019-05-17 10:12                   ` [PATCH v2 2/3] x86/cpuidle: push parked CPUs into deeper sleep states when possible Jan Beulich
2019-05-17 10:12                     ` [Xen-devel] " Jan Beulich
2019-05-17 10:12                   ` [PATCH v2 3/3] x86/cpuidle: clean up Cx dumping Jan Beulich
2019-05-17 10:12                     ` [Xen-devel] " Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5B61C47D02000078001D9F65@prv1-mh.provo.novell.com \
    --to=jbeulich@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).