All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Hardware Monitoring <linux-hwmon@vger.kernel.org>
Cc: Jean Delvare <jdelvare@suse.com>,
	Guenter Roeck <linux@roeck-us.net>,
	Naveen Krishna Chatradhi <nchatrad@amd.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: [PATCH v2 2/2] hwmon: (amd_energy) Restore visibility of energy counters
Date: Fri,  9 Apr 2021 10:48:52 -0700	[thread overview]
Message-ID: <20210409174852.4585-2-linux@roeck-us.net> (raw)
In-Reply-To: <20210409174852.4585-1-linux@roeck-us.net>

Commit 60268b0e8258 ("hwmon: (amd_energy) modify the visibility of
the counters") restricted visibility of AMD energy counters to work
around a side-channel attack using energy data to determine which
instructions are executed. The attack is described in 'PLATYPUS:
Software-based Power Side-Channel Attacks on x86'. It relies on quick
and accurate energy readings.

Limiting energy readings to privileged users is annoying. A much better
solution is to make energy readings unusable for attacks by randomizing
the time between updates. We can do that by caching energy values for
a short and randomized period of time.

Cc: Naveen Krishna Chatradhi <nchatrad@amd.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
v2: Simplified code by using unified function to accumulate energy data

 drivers/hwmon/amd_energy.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/hwmon/amd_energy.c b/drivers/hwmon/amd_energy.c
index 93bad64039f1..1bf0afc2740c 100644
--- a/drivers/hwmon/amd_energy.c
+++ b/drivers/hwmon/amd_energy.c
@@ -18,6 +18,7 @@
 #include <linux/mutex.h>
 #include <linux/processor.h>
 #include <linux/platform_device.h>
+#include <linux/random.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/topology.h>
@@ -35,6 +36,7 @@
 struct sensor_accumulator {
 	u64 energy_ctr;
 	u64 prev_value;
+	unsigned long cache_timeout;
 };
 
 struct amd_energy_data {
@@ -74,17 +76,14 @@ static void get_energy_units(struct amd_energy_data *data)
 	data->energy_units = (rapl_units & AMD_ENERGY_UNIT_MASK) >> 8;
 }
 
-static void accumulate_delta(struct amd_energy_data *data,
-			     int channel, int cpu, u32 reg)
+static void __accumulate_delta(struct sensor_accumulator *accum,
+			       int cpu, u32 reg)
 {
-	struct sensor_accumulator *accum;
 	u64 input;
 
-	mutex_lock(&data->lock);
 	rdmsrl_safe_on_cpu(cpu, reg, &input);
 	input &= AMD_ENERGY_MASK;
 
-	accum = &data->accums[channel];
 	if (input >= accum->prev_value)
 		accum->energy_ctr +=
 			input - accum->prev_value;
@@ -93,6 +92,14 @@ static void accumulate_delta(struct amd_energy_data *data,
 			accum->prev_value + input;
 
 	accum->prev_value = input;
+	accum->cache_timeout = jiffies + HZ + get_random_int() % HZ;
+}
+
+static void accumulate_delta(struct amd_energy_data *data,
+			     int channel, int cpu, u32 reg)
+{
+	mutex_lock(&data->lock);
+	__accumulate_delta(&data->accums[channel], cpu, reg);
 	mutex_unlock(&data->lock);
 }
 
@@ -124,6 +131,7 @@ static int amd_energy_read(struct device *dev,
 {
 	struct amd_energy_data *data = dev_get_drvdata(dev);
 	struct sensor_accumulator *accum;
+	u64 energy;
 	u32 reg;
 	int cpu;
 
@@ -140,10 +148,15 @@ static int amd_energy_read(struct device *dev,
 		reg = ENERGY_CORE_MSR;
 	}
 
-	accumulate_delta(data, channel, cpu, reg);
 	accum = &data->accums[channel];
 
-	*val = div64_ul(accum->energy_ctr * 1000000UL, BIT(data->energy_units));
+	mutex_lock(&data->lock);
+	if (!accum->energy_ctr || time_after(jiffies, accum->cache_timeout))
+		__accumulate_delta(accum, cpu, reg);
+	energy = accum->energy_ctr;
+	mutex_unlock(&data->lock);
+
+	*val = div64_ul(energy * 1000000UL, BIT(data->energy_units));
 
 	return 0;
 }
@@ -152,7 +165,7 @@ static umode_t amd_energy_is_visible(const void *_data,
 				     enum hwmon_sensor_types type,
 				     u32 attr, int channel)
 {
-	return 0440;
+	return 0444;
 }
 
 static int energy_accumulator(void *p)
-- 
2.17.1


  reply	other threads:[~2021-04-09 17:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-09 17:48 [PATCH v2 1/2] hwmon: (amd_energy) Use unified function to read energy data Guenter Roeck
2021-04-09 17:48 ` Guenter Roeck [this message]
2021-04-12 12:27   ` [PATCH v2 2/2] hwmon: (amd_energy) Restore visibility of energy counters Jean Delvare
2021-04-12 14:25     ` Guenter Roeck
2021-04-19 16:29       ` Chatradhi, Naveen Krishna
2021-04-19 17:41         ` Guenter Roeck
2021-04-12 12:14 ` [PATCH v2 1/2] hwmon: (amd_energy) Use unified function to read energy data Jean Delvare
2021-04-12 14:17   ` Guenter Roeck

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=20210409174852.4585-2-linux@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=jdelvare@suse.com \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=nchatrad@amd.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.