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  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20200919044725.2148-1-zhuguangqing83@gmail.com>
Date:   Sat, 19 Sep 2020 12:47:25 +0800
From:   zhuguangqing83@...il.com
To:     amit.kachhap@...il.com, daniel.lezcano@...aro.org,
        viresh.kumar@...aro.org, javi.merino@...nel.org,
        rui.zhang@...el.com, amitk@...nel.org
Cc:     linux-pm@...r.kernel.org, linux-kernel@...r.kernel.org,
        zhuguangqing <zhuguangqing@...omi.com>
Subject: [PATCH] thermal/drivers/cpuidle_cooling: Change the latency limit

From: zhuguangqing <zhuguangqing@...omi.com>

The injected idle duration must be greater than the wake up latency
(entry + exit latency) or the idle state target residency (or  min
residency), otherwise we end up consuming more energy and potentially
invert the mitigation effect.

In function idle_inject_fn(), we call play_idle_precise() to specify
a latency limit which is finally used in find_deepest_state() to find
the deepest idle state. Although the latency limit is compared with
s->exit_latency_ns in find_deepest_state(), it should not be exit
latency, but the idle duraion minus entry latency which can ensure
that the injected idle duration is greater than the wake up latency
(entry + exit latency).

There are two timers in idle inject process, the length of the first
timer (timer_1) is idle duration, and the length of the second timer
(timer_2) is idle duration plus run duration. When timer_2 expires,
it's restarted and idle_inject_timer_fn() is called and it wakes up
idle injection tasks associated with the timer and they, in turn,
invoke play_idle_precise() to inject a specified amount (idle duration)
of CPU idle time. The major functions called are as follows:

play_idle_precise() ->
 do_idle() ->
  cpuidle_idle_call() ->
   cpuidle_find_deepest_state() ->
    find_deepest_state()

When we call find_deepest_state(), some time has been consumed from
the beginning of the idle duration which could be considered the
entry latency approximately, so the latency limit should be the idle
duraion minus entry latency which can ensure that the injected idle
duration is greater than the wake up latency (entry + exit latency).

Here are two sample scenes,
scene   entry latency(us)    exit latency(us)    idle duration(us)
1            500                     600               1000
2            500                     600               3000

In scene 1, if we use exit latency (600us) for the latency limit,
we may find a idle state which has a exit latency equal to or less
than 600us, suppose the idle state's exit latency is equal to 600us,
then the wake up latency (entry + exit latency) is greater than idle
duration.

In scene 2, if we use exit latency (600us) for the latency limit,
we may also find a idle state which has a exit latency equal to
600us. But if we use the idle duraion minus entry latency
(3000 - 500 = 2500us), we can find a deeper idle state to save
more power in idle duration.

Signed-off-by: zhuguangqing <zhuguangqing@...omi.com>
---
 drivers/thermal/cpuidle_cooling.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/cpuidle_cooling.c b/drivers/thermal/cpuidle_cooling.c
index 78e3e8238116..6f78c7816fcc 100644
--- a/drivers/thermal/cpuidle_cooling.c
+++ b/drivers/thermal/cpuidle_cooling.c
@@ -174,6 +174,7 @@ static int __cpuidle_cooling_register(struct device_node *np,
 	struct idle_inject_device *ii_dev;
 	struct cpuidle_cooling_device *idle_cdev;
 	struct thermal_cooling_device *cdev;
+	unsigned int entry_latency_us;
 	unsigned int idle_duration_us = TICK_USEC;
 	unsigned int latency_us = UINT_MAX;
 	char dev_name[THERMAL_NAME_LENGTH];
@@ -198,7 +199,9 @@ static int __cpuidle_cooling_register(struct device_node *np,
 	}
 
 	of_property_read_u32(np, "duration-us", &idle_duration_us);
-	of_property_read_u32(np, "exit-latency-us", &latency_us);
+	if (!of_property_read_u32(np, "entry-latency-us", &entry_latency_us) &&
+	    idle_duration_us > entry_latency_us)
+		latency_us = idle_duration_us - entry_latency_us;
 
 	idle_inject_set_duration(ii_dev, TICK_USEC, idle_duration_us);
 	idle_inject_set_latency(ii_dev, latency_us);
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ