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>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250529001315.233492-10-changwoo@igalia.com>
Date: Thu, 29 May 2025 09:13:13 +0900
From: Changwoo Min <changwoo@...lia.com>
To: lukasz.luba@....com,
	rafael@...nel.org,
	len.brown@...el.com,
	pavel@...nel.org
Cc: christian.loehle@....com,
	tj@...nel.org,
	kernel-dev@...lia.com,
	linux-pm@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	Changwoo Min <changwoo@...lia.com>
Subject: [PATCH 09/11] PM: EM: Implement EM_GENL_CMD_PD_GET_TBL.

When a userspace requests EM_GENL_CMD_PD_GET_TBL with an ID of a
performance domain, the kernel reports back the energy model table of the
specified performance domain. The message format of the response is as
follows:

EM_GENL_ATTR_PD_TBL (NLA_NESTED)
	EM_TBL_ENTRY_GENL_ATTR_PD (NLA_NESTED)*
		EM_TBL_GENL_ATTR_PS_PERFORMANCE (NLA_U64)
		EM_TBL_GENL_ATTR_PS_FREQUENCY (NLA_U64)
		EM_TBL_GENL_ATTR_PS_POWER (NLA_U64)
		EM_TBL_GENL_ATTR_PS_COST (NLA_U64)
		EM_TBL_GENL_ATTR_PS_FLAGS (NLA_U64)

Where EM_TBL_ENTRY_GENL_ATTR_PD can be repeated as many times as there are
performance states (struct em_perf_state).

Signed-off-by: Changwoo Min <changwoo@...lia.com>
---
 include/uapi/linux/energy_model.h | 24 ++++++++++++
 kernel/power/em_netlink.c         | 64 ++++++++++++++++++++++++++++++-
 2 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/energy_model.h b/include/uapi/linux/energy_model.h
index 66339ace6fcb..9517ca957a78 100644
--- a/include/uapi/linux/energy_model.h
+++ b/include/uapi/linux/energy_model.h
@@ -12,6 +12,7 @@ enum em_genl_attr {
 	EM_GENL_ATTR_UNSPEC,
 	EM_GENL_ATTR_PAD = EM_GENL_ATTR_UNSPEC,
 	EM_GENL_ATTR_PD,	/* Performance domain */
+	EM_GENL_ATTR_PD_TBL,	/* Performance table of a performance domain */
 	__EM_GENL_ATTR_MAX,
 };
 #define EM_GENL_ATTR_MAX (__EM_GENL_ATTR_MAX - 1)
@@ -39,6 +40,29 @@ enum em_pd_genl_attr {
 
 #define EM_PD_CPUS_LENGTH		256
 
+enum em_tbl_entry_genl_attr {
+	EM_TBL_ENTRY_GENL_ATTR_UNSPEC,
+	EM_TBL_ENTRY_GENL_ATTR_PAD = EM_TBL_ENTRY_GENL_ATTR_UNSPEC,
+	EM_TBL_ENTRY_GENL_ATTR_PD,
+	__EM_TBL_ENTRY_GENL_ATTR_MAX,
+};
+#define EM_TBL_ENTRY_GENL_ATTR_MAX (__EM_TBL_ENTRY_GENL_ATTR_MAX - 1)
+
+enum em_tbl_genl_attr {
+	EM_TBL_GENL_ATTR_UNSPEC,
+	EM_TBL_GENL_ATTR_PAD = EM_TBL_GENL_ATTR_UNSPEC,
+
+	/* Performance table of a performance domain */
+	EM_TBL_GENL_ATTR_PS_PERFORMANCE,
+	EM_TBL_GENL_ATTR_PS_FREQUENCY,
+	EM_TBL_GENL_ATTR_PS_POWER,
+	EM_TBL_GENL_ATTR_PS_COST,
+	EM_TBL_GENL_ATTR_PS_FLAGS,
+
+	__EM_TBL_GENL_ATTR_MAX,
+};
+#define EM_TBL_GENL_ATTR_MAX (__EM_TBL_GENL_ATTR_MAX - 1)
+
 /* Events of em_genl_family */
 enum em_genl_event {
 	EM_GENL_EVENT_UNSPEC,
diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index ea975ca6272f..5f3d5aaa97d7 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -23,6 +23,8 @@ static const struct genl_multicast_group em_genl_mcgrps[] = {
 static const struct nla_policy em_genl_policy[EM_GENL_ATTR_MAX + 1] = {
 	/* Performance domain */
 	[EM_GENL_ATTR_PD]			= { .type = NLA_NESTED },
+	/* Performance table of a performance domain */
+	[EM_GENL_ATTR_PD_TBL]			= { .type = NLA_NESTED },
 };
 
 struct param {
@@ -94,7 +96,67 @@ static int em_genl_cmd_pd_get_id(struct param *p)
 
 static int em_genl_cmd_pd_get_tbl(struct param *p)
 {
-	return -ENOTSUPP;
+	struct sk_buff *msg = p->msg;
+	struct em_perf_domain *pd;
+	struct em_perf_state *table, *ps;
+	struct nlattr *start_tbl, *entry;
+	int id, i;
+
+	if (!p->attrs[EM_PD_GENL_ATTR_ID])
+		return -EINVAL;
+
+	id = nla_get_u32(p->attrs[EM_PD_GENL_ATTR_ID]);
+
+	pd = em_perf_domain_get_by_id(id);
+	if (!pd)
+		return -EINVAL;
+
+	start_tbl = nla_nest_start(msg, EM_GENL_ATTR_PD_TBL);
+	if (!start_tbl )
+		return -EMSGSIZE;
+
+	rcu_read_lock();
+	table = em_perf_state_from_pd(pd);
+
+	for (i = 0; i < pd->nr_perf_states; i++) {
+		ps = &table[i];
+
+		entry = nla_nest_start(msg, EM_TBL_ENTRY_GENL_ATTR_PD);
+		if (!entry)
+			goto out_cancel_nest;
+
+		if (nla_put_u64_64bit(msg, EM_TBL_GENL_ATTR_PS_PERFORMANCE,
+				      ps->performance, EM_TBL_GENL_ATTR_PAD))
+			goto out_cancel_nest2;
+		if (nla_put_u64_64bit(msg, EM_TBL_GENL_ATTR_PS_FREQUENCY,
+				      ps->frequency, EM_TBL_GENL_ATTR_PAD))
+			goto out_cancel_nest2;
+		if (nla_put_u64_64bit(msg, EM_TBL_GENL_ATTR_PS_POWER,
+				      ps->power, EM_TBL_GENL_ATTR_PAD))
+			goto out_cancel_nest2;
+		if (nla_put_u64_64bit(msg, EM_TBL_GENL_ATTR_PS_COST,
+				      ps->cost, EM_TBL_GENL_ATTR_PAD))
+			goto out_cancel_nest2;
+		if (nla_put_u64_64bit(msg, EM_TBL_GENL_ATTR_PS_FLAGS,
+				      ps->flags, EM_TBL_GENL_ATTR_PAD))
+			goto out_cancel_nest2;
+
+		nla_nest_end(msg, entry);
+	}
+	rcu_read_unlock();
+
+	nla_nest_end(msg, start_tbl);
+
+	return 0;
+
+out_cancel_nest2:
+	nla_nest_cancel(msg, entry);
+
+out_cancel_nest:
+	rcu_read_unlock();
+
+	nla_nest_cancel(msg, start_tbl);
+	return -EMSGSIZE;
 }
 
 static const cb_t cmd_cb[] = {
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ