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

[Xen-devel] Ping: [PATCH 3/5] x86/cpuidle: push parked CPUs into deeper sleep states when possible



>>> On 01.08.18 at 16:32,  wrote:
> 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@xxxxxxxx>
> 
> --- 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@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®.