lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 9 Nov 2017 08:51:04 +0100
From:   Vincent Guittot <vincent.guittot@...aro.org>
To:     Len Brown <lenb@...nel.org>
Cc:     thomas.ilsche@...dresden.de, dsmythies@...us.net,
        "linux-pm@...r.kernel.org" <linux-pm@...r.kernel.org>,
        jacob.jun.pan@...ux.intel.com,
        linux-kernel <linux-kernel@...r.kernel.org>,
        Len Brown <len.brown@...el.com>
Subject: Re: [PATCH] cpuidle: Add "cpuidle.use_deepest" to bypass governor and
 allow HW to go deep

Hi Len

On 9 November 2017 at 08:38, Len Brown <lenb@...nel.org> wrote:
> From: Len Brown <len.brown@...el.com>
>
> While there are several mechanisms (cmdline, sysfs, PM_QOS) to limit
> cpuidle to shallow idle states, there is no simple mechanism
> to give the hardware permission to enter the deeptest state permitted by PM_QOS.

and by per device resume latency QoS

>
> Here we create the "cpuidle.use_deepest" modparam to provide this capability.
>
> "cpuidle.use_deepest=Y" can be set at boot-time, and
> /sys/module/cpuidle/use_deepest can be modified (with Y/N) at run-time.
>
> n.b.
>
> Within the constraints of PM_QOS, this mechanism gives the hardware
> permission to choose the deeptest power savings and highest latency
> state available.  And so choice will depend on the particular hardware.
>
> Also, if PM_QOS is not informed of latency constraints, it can't help.
> In that case, using this mechanism may result in entering high-latency
> states that impact performance.
>
> Signed-off-by: Len Brown <len.brown@...el.com>
> ---
>  Documentation/admin-guide/kernel-parameters.txt |  4 ++++
>  drivers/cpuidle/cpuidle.c                       | 19 ++++++++++++++++
>  include/linux/cpuidle.h                         |  7 ++++++
>  kernel/sched/idle.c                             | 30 +++++++++++++++++++------
>  4 files changed, 53 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 05496622b4ef..20f70de688bf 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -659,6 +659,10 @@
>         cpuidle.off=1   [CPU_IDLE]
>                         disable the cpuidle sub-system
>
> +       cpuidle.use_deepest=Y   [CPU_IDLE]
> +                       Ignore cpuidle governor, always choose deepest
> +                       PM_QOS-legal CPU idle power saving state.
> +
>         cpufreq.off=1   [CPU_FREQ]
>                         disable the cpufreq sub-system
>
> diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
> index 484cc8909d5c..afee5aab7719 100644
> --- a/drivers/cpuidle/cpuidle.c
> +++ b/drivers/cpuidle/cpuidle.c
> @@ -34,6 +34,7 @@ LIST_HEAD(cpuidle_detected_devices);
>
>  static int enabled_devices;
>  static int off __read_mostly;
> +static bool use_deepest __read_mostly;
>  static int initialized __read_mostly;
>
>  int cpuidle_disabled(void)
> @@ -116,6 +117,10 @@ void cpuidle_use_deepest_state(bool enable)
>         preempt_enable();
>  }
>
> +bool cpuidle_using_deepest_state(void)
> +{
> +       return use_deepest;
> +}
>  /**
>   * cpuidle_find_deepest_state - Find the deepest available idle state.
>   * @drv: cpuidle driver for the given CPU.
> @@ -127,6 +132,19 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
>         return find_deepest_state(drv, dev, UINT_MAX, 0, false);
>  }
>
> +/**
> + * cpuidle_find_deepest_state_qos - Find the deepest available idle state.
> + * @drv: cpuidle driver for the given CPU.
> + * @dev: cpuidle device for the given CPU.
> + * Honors PM_QOS
> + */
> +int cpuidle_find_deepest_state_qos(struct cpuidle_driver *drv,
> +                              struct cpuidle_device *dev)
> +{
> +       return find_deepest_state(drv, dev,
> +                       pm_qos_request(PM_QOS_CPU_DMA_LATENCY), 0, false);

You should also take into account per device latency  like in menu governor:
dev_pm_qos_raw_read_value(device);


> +}
> +
>  #ifdef CONFIG_SUSPEND
>  static void enter_s2idle_proper(struct cpuidle_driver *drv,
>                                 struct cpuidle_device *dev, int index)
> @@ -681,4 +699,5 @@ static int __init cpuidle_init(void)
>  }
>
>  module_param(off, int, 0444);
> +module_param(use_deepest, bool, 0644);
>  core_initcall(cpuidle_init);
> diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
> index 8f7788d23b57..e3c2c9d1898f 100644
> --- a/include/linux/cpuidle.h
> +++ b/include/linux/cpuidle.h
> @@ -198,19 +198,26 @@ static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; }
>  #ifdef CONFIG_CPU_IDLE
>  extern int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
>                                       struct cpuidle_device *dev);
> +extern int cpuidle_find_deepest_state_qos(struct cpuidle_driver *drv,
> +                                     struct cpuidle_device *dev);
>  extern int cpuidle_enter_s2idle(struct cpuidle_driver *drv,
>                                 struct cpuidle_device *dev);
>  extern void cpuidle_use_deepest_state(bool enable);
> +extern bool cpuidle_using_deepest_state(void);
>  #else
>  static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
>                                              struct cpuidle_device *dev)
>  {return -ENODEV; }
> +static inline int cpuidle_find_deepest_state_qos(struct cpuidle_driver *drv,
> +                                            struct cpuidle_device *dev)
> +{return -ENODEV; }
>  static inline int cpuidle_enter_s2idle(struct cpuidle_driver *drv,
>                                        struct cpuidle_device *dev)
>  {return -ENODEV; }
>  static inline void cpuidle_use_deepest_state(bool enable)
>  {
>  }
> +static inline bool cpuidle_using_deepest_state(void) {return false; }
>  #endif
>
>  /* kernel/sched/idle.c */
> diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
> index 257f4f0b4532..6c7348ae28ec 100644
> --- a/kernel/sched/idle.c
> +++ b/kernel/sched/idle.c
> @@ -167,17 +167,33 @@ static void cpuidle_idle_call(void)
>          * until a proper wakeup interrupt happens.
>          */
>
> -       if (idle_should_enter_s2idle() || dev->use_deepest_state) {
> -               if (idle_should_enter_s2idle()) {
> -                       entered_state = cpuidle_enter_s2idle(drv, dev);
> -                       if (entered_state > 0) {
> -                               local_irq_enable();
> -                               goto exit_idle;
> -                       }
> +       if (idle_should_enter_s2idle()) {
> +               entered_state = cpuidle_enter_s2idle(drv, dev);
> +               if (entered_state > 0) {
> +                       local_irq_enable();
> +                       goto exit_idle;
>                 }
> +       }
>
> +       /*
> +        * cpuidle_dev->user_deepest_state is per-device, and thus per-CPU.
> +        * it is used to force power-savings, and thus does not obey PM_QOS.
> +        */
> +
> +       if (dev->use_deepest_state) {
>                 next_state = cpuidle_find_deepest_state(drv, dev);
>                 call_cpuidle(drv, dev, next_state);
> +       }
> +
> +       /*
> +        * cpuidle_using_deepest_state() is system-wide, applying to all CPUs.
> +        * When activated, Linux gives the hardware permission to go as deep
> +        * as PM_QOS allows.
> +        */
> +
> +       else if (cpuidle_using_deepest_state()) {
> +               next_state = cpuidle_find_deepest_state_qos(drv, dev);
> +               call_cpuidle(drv, dev, next_state);
>         } else {
>                 /*
>                  * Ask the cpuidle framework to choose a convenient idle state.
> --
> 2.14.0-rc0
>

Powered by blists - more mailing lists