[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/3] mwait-idle: add support for using halt



Some AMD processors can use a mixture of mwait and halt for accessing
various c-states.  In preparation for adding support for AMD processors,
update the mwait-idle driver to optionally use halt.

Signed-off-by: Brian Woods <brian.woods@xxxxxxx>
---
 xen/arch/x86/cpu/mwait-idle.c | 40 +++++++++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/xen/arch/x86/cpu/mwait-idle.c b/xen/arch/x86/cpu/mwait-idle.c
index f89c52f256..a063e39d60 100644
--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -103,6 +103,11 @@ static const struct cpuidle_state {
 
 #define CPUIDLE_FLAG_DISABLED          0x1
 /*
+ * On certain AMD families that support mwait, only c1 can be reached by
+ * mwait and to reach c2, halt has to be used.
+ */
+#define CPUIDLE_FLAG_USE_HALT          0x2
+/*
  * Set this flag for states where the HW flushes the TLB for us
  * and so we don't need cross-calls to keep it consistent.
  * If this flag is set, SW flushes the TLB, so even if the
@@ -783,8 +788,23 @@ static void mwait_idle(void)
 
        update_last_cx_stat(power, cx, before);
 
-       if (cpu_is_haltable(cpu))
-               mwait_idle_with_hints(eax, MWAIT_ECX_INTERRUPT_BREAK);
+       if (cpu_is_haltable(cpu)) {
+               struct cpu_info *info;
+               switch (cx->entry_method) {
+               case ACPI_CSTATE_EM_FFH:
+                       mwait_idle_with_hints(eax, MWAIT_ECX_INTERRUPT_BREAK);
+                       break;
+               case ACPI_CSTATE_EM_HALT:
+                       info = get_cpu_info();
+                       spec_ctrl_enter_idle(info);
+                       safe_halt();
+                       spec_ctrl_exit_idle(info);
+                       local_irq_disable();
+                       break;
+               default:
+                       printk(XENLOG_ERR PREFIX "unknown entry method %d\n", 
cx->entry_method);
+               }
+       }
 
        after = cpuidle_get_tick();
 
@@ -1184,8 +1204,9 @@ static int mwait_idle_cpu_init(struct notifier_block *nfb,
        for (cstate = 0; cpuidle_state_table[cstate].target_residency; 
++cstate) {
                unsigned int num_substates, hint, state;
                struct acpi_processor_cx *cx;
+               const unsigned int flags = cpuidle_state_table[cstate].flags;
 
-               hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
+               hint = flg2MWAIT(flags);
                state = MWAIT_HINT2CSTATE(hint) + 1;
 
                if (state > max_cstate) {
@@ -1196,13 +1217,13 @@ static int mwait_idle_cpu_init(struct notifier_block 
*nfb,
                /* Number of sub-states for this state in CPUID.MWAIT. */
                num_substates = (mwait_substates >> (state * 4))
                                & MWAIT_SUBSTATE_MASK;
+
                /* If NO sub-states for this state in CPUID, skip it. */
-               if (num_substates == 0)
+               if (num_substates == 0 && !(flags & CPUIDLE_FLAG_USE_HALT))
                        continue;
 
                /* if state marked as disabled, skip it */
-               if (cpuidle_state_table[cstate].flags &
-                   CPUIDLE_FLAG_DISABLED) {
+               if (flags & CPUIDLE_FLAG_DISABLED) {
                        printk(XENLOG_DEBUG PREFIX "state %s is disabled",
                               cpuidle_state_table[cstate].name);
                        continue;
@@ -1221,7 +1242,12 @@ static int mwait_idle_cpu_init(struct notifier_block 
*nfb,
                cx = dev->states + dev->count;
                cx->type = state;
                cx->address = hint;
-               cx->entry_method = ACPI_CSTATE_EM_FFH;
+
+               if (flags & CPUIDLE_FLAG_USE_HALT)
+                       cx->entry_method = ACPI_CSTATE_EM_HALT;
+                else
+                       cx->entry_method = ACPI_CSTATE_EM_FFH;
+
                cx->latency = cpuidle_state_table[cstate].exit_latency;
                cx->target_residency =
                        cpuidle_state_table[cstate].target_residency;
-- 
2.11.0


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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.