* [PATCH 0/3] platform/x86/amd/pmf: introduce AMD PMF util layer and user-space interface for SystemDeck
@ 2025-10-17 10:25 Shyam Sundar S K
2025-10-17 10:25 ` [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface Shyam Sundar S K
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Shyam Sundar S K @ 2025-10-17 10:25 UTC (permalink / raw)
To: hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello, Yijun.Shen,
Sanket.Goswami, Shyam Sundar S K
This series introduces a util layer to the AMD Platform Management
Framework (PMF) and a minimal user-space interface via a misc character
device, enabling feature discovery and smoother integration with
user-space tools. It also adds caching of BIOS output policy values to
prepare for user-space telemetry reporting via IOCTLs.
The motivation is to provide a stable interface for user-space tools to
discover PMF features and consume selected metrics. Enable smoother
integration with AMD SystemDeck, a widely used tool for monitoring and
controlling power and thermal behavior, helping designers keep components
within thermal limits to ensure proper operation and improve system
stability and reliability.
Shyam Sundar S K (3):
platform/x86/amd/pmf: add util layer and user-space misc device
interface
platform/x86/amd/pmf: cache BIOS output values for user-space
telemetry via util IOCTL
Documentation/ABI: add testing entry for AMD PMF misc device interface
.../ABI/testing/misc-amdpmf_interface | 55 ++++
MAINTAINERS | 1 +
drivers/platform/x86/amd/pmf/Kconfig | 10 +
drivers/platform/x86/amd/pmf/Makefile | 2 +
drivers/platform/x86/amd/pmf/core.c | 19 ++
drivers/platform/x86/amd/pmf/pmf.h | 11 +
drivers/platform/x86/amd/pmf/tee-if.c | 10 +
drivers/platform/x86/amd/pmf/util.c | 305 ++++++++++++++++++
8 files changed, 413 insertions(+)
create mode 100644 Documentation/ABI/testing/misc-amdpmf_interface
create mode 100644 drivers/platform/x86/amd/pmf/util.c
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface
2025-10-17 10:25 [PATCH 0/3] platform/x86/amd/pmf: introduce AMD PMF util layer and user-space interface for SystemDeck Shyam Sundar S K
@ 2025-10-17 10:25 ` Shyam Sundar S K
2025-10-17 15:10 ` Mario Limonciello
2025-10-17 10:25 ` [PATCH 2/3] platform/x86/amd/pmf: cache BIOS output values for user-space telemetry via util IOCTL Shyam Sundar S K
2025-10-17 10:25 ` [PATCH 3/3] Documentation/ABI: add testing entry for AMD PMF misc device interface Shyam Sundar S K
2 siblings, 1 reply; 7+ messages in thread
From: Shyam Sundar S K @ 2025-10-17 10:25 UTC (permalink / raw)
To: hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello, Yijun.Shen,
Sanket.Goswami, Shyam Sundar S K
Add a util layer to AMD PMF that exposes a minimal user-space interface
via a misc character device for metrics monitoring and feature discovery.
This creates /dev/amdpmf_interface with a basic ioctl to report support
for PMF features (Smart PC Builder, Auto Mode, Static Power Slider,
Dynamic Power Slider AC/DC), enabling smoother integration with
user-space tools such as AMD SystemDeck[1].
AMD SystemDeck is a widely used user-space tool for monitoring and
controlling power and thermal behavior. It helps designers keep major
components within their thermal limits to ensure proper operation.
Maintaining temperatures within specification enhances overall system
stability and reliability.
[1] https://docs.amd.com/v/u/en-US/68773_0.50
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/Kconfig | 10 +++
drivers/platform/x86/amd/pmf/Makefile | 2 +
drivers/platform/x86/amd/pmf/core.c | 19 +++++
drivers/platform/x86/amd/pmf/pmf.h | 10 +++
drivers/platform/x86/amd/pmf/util.c | 115 ++++++++++++++++++++++++++
5 files changed, 156 insertions(+)
create mode 100644 drivers/platform/x86/amd/pmf/util.c
diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 25b8f7ae3abd..81ea4934e199 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -30,3 +30,13 @@ config AMD_PMF_DEBUG
in the PMF config store.
Say Y here to enable more debug logs and Say N here if you are not sure.
+
+config AMD_PMF_UTIL_SUPPORT
+ bool "AMD PMF Util layer support"
+ depends on AMD_PMF
+ help
+ Enabling this option permits the driver to interface with user
+ space for capturing AMD PMF metrics and updating them to the
+ user space tool for smooth monitoring.
+
+ Say Y here to enable it and Say N here if you are not sure.
diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
index 5978464e0eb7..bf7aad80b9e9 100644
--- a/drivers/platform/x86/amd/pmf/Makefile
+++ b/drivers/platform/x86/amd/pmf/Makefile
@@ -8,3 +8,5 @@ obj-$(CONFIG_AMD_PMF) += amd-pmf.o
amd-pmf-y := core.o acpi.o sps.o \
auto-mode.o cnqf.o \
tee-if.o spc.o
+# Build util.c only when AMD_PMF_UTIL_SUPPORT is enabled
+amd-pmf-$(CONFIG_AMD_PMF_UTIL_SUPPORT) += util.o
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index bc544a4a5266..ac2b80db019e 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -53,6 +53,19 @@ static bool force_load;
module_param(force_load, bool, 0444);
MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
+#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
+struct amd_pmf_dev *pmf_handle;
+
+struct amd_pmf_dev *amd_pmf_get_handle(void)
+{
+ struct amd_pmf_dev *pmf = pmf_handle;
+
+ return pmf;
+}
+#else
+struct amd_pmf_dev *amd_pmf_get_handle(void) { return NULL; }
+#endif
+
static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
{
struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
@@ -465,6 +478,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
if (!dev->regbase)
return -ENOMEM;
+#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
+ pmf_handle = dev;
+#endif
+
mutex_init(&dev->lock);
mutex_init(&dev->update_mutex);
mutex_init(&dev->cb_mutex);
@@ -477,6 +494,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD);
+ amd_pmf_cdev_register();
dev_info(dev->dev, "registered PMF device successfully\n");
return 0;
@@ -489,6 +507,7 @@ static void amd_pmf_remove(struct platform_device *pdev)
amd_pmf_deinit_features(dev);
if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_UNLOAD);
+ amd_pmf_cdev_unregister();
apmf_acpi_deinit(dev);
amd_pmf_dbgfs_unregister(dev);
mutex_destroy(&dev->lock);
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index bd19f2a6bc78..3b1aae8a60a5 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -823,6 +823,7 @@ struct ta_pmf_shared_memory {
};
/* Core Layer */
+struct amd_pmf_dev *amd_pmf_get_handle(void);
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
int is_apmf_func_supported(struct amd_pmf_dev *pdev, unsigned long index);
@@ -888,4 +889,13 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev);
+/* Util Layer */
+#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
+int amd_pmf_cdev_register(void);
+void amd_pmf_cdev_unregister(void);
+#else
+static inline int amd_pmf_cdev_register(void) { return 0; }
+static inline void amd_pmf_cdev_unregister(void) {}
+#endif
+
#endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
new file mode 100644
index 000000000000..483e4531535e
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/util.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Platform Management Framework Util Layer
+ *
+ * Copyright (c) 2025, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ * Sanket Goswami <Sanket.Goswami@amd.com>
+ */
+
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+
+#include "pmf.h"
+
+#define IOCTL_PMF_QUERY_FEATURE_SUPPORT 0
+
+/* AMD PMF Feature IDs */
+#define PMF_FEATURE_AUTO_MODE 0
+#define PMF_FEATURE_STATIC_POWER_SLIDER 2
+#define PMF_FEATURE_POLICY_BUILDER 4
+#define PMF_FEATURE_DYNAMIC_POWER_SLIDER_AC 5
+#define PMF_FEATURE_DYNAMIC_POWER_SLIDER_DC 6
+
+#define AMD_PMF_FEATURE_VERSION 0x02
+
+struct amd_pmf_feature_support {
+ bool feature_supported;
+ unsigned long feature_version;
+ unsigned long feature_id;
+};
+
+static int amd_pmf_get_feature_status(void __user *argp, unsigned long feat_id)
+{
+ struct amd_pmf_feature_support info;
+ struct amd_pmf_dev *pdev;
+
+ pdev = amd_pmf_get_handle();
+ if (!pdev)
+ return -EINVAL;
+
+ switch (feat_id) {
+ case PMF_FEATURE_AUTO_MODE:
+ info.feature_supported = is_apmf_func_supported(pdev, APMF_FUNC_AUTO_MODE);
+ break;
+ case PMF_FEATURE_STATIC_POWER_SLIDER:
+ info.feature_supported = is_apmf_func_supported(pdev,
+ APMF_FUNC_STATIC_SLIDER_GRANULAR);
+ break;
+ case PMF_FEATURE_POLICY_BUILDER:
+ info.feature_supported = pdev->smart_pc_enabled;
+ break;
+ case PMF_FEATURE_DYNAMIC_POWER_SLIDER_AC:
+ info.feature_supported = is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_AC);
+ break;
+ case PMF_FEATURE_DYNAMIC_POWER_SLIDER_DC:
+ info.feature_supported = is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_DC);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ info.feature_version = AMD_PMF_FEATURE_VERSION;
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct amd_pmf_feature_support output;
+ int ret = -ENOTTY;
+
+ ret = copy_from_user(&output, argp, sizeof(output));
+ if (ret)
+ return -EFAULT;
+
+ switch (cmd) {
+ case IOCTL_PMF_QUERY_FEATURE_SUPPORT:
+ ret = amd_pmf_get_feature_status(argp, output.feature_id);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct file_operations pmf_if_ops = {
+ .unlocked_ioctl = amd_pmf_set_ioctl,
+};
+
+#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
+static struct miscdevice amd_pmf_util_if = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "amdpmf_interface",
+ .fops = &pmf_if_ops,
+};
+
+int amd_pmf_cdev_register(void)
+{
+ return misc_register(&amd_pmf_util_if);
+}
+
+void amd_pmf_cdev_unregister(void)
+{
+ misc_deregister(&amd_pmf_util_if);
+}
+#else
+int amd_pmf_cdev_register(void) { return 0; }
+void amd_pmf_cdev_unregister(void) {}
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] platform/x86/amd/pmf: cache BIOS output values for user-space telemetry via util IOCTL
2025-10-17 10:25 [PATCH 0/3] platform/x86/amd/pmf: introduce AMD PMF util layer and user-space interface for SystemDeck Shyam Sundar S K
2025-10-17 10:25 ` [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface Shyam Sundar S K
@ 2025-10-17 10:25 ` Shyam Sundar S K
2025-10-17 15:17 ` Mario Limonciello
2025-10-17 10:25 ` [PATCH 3/3] Documentation/ABI: add testing entry for AMD PMF misc device interface Shyam Sundar S K
2 siblings, 1 reply; 7+ messages in thread
From: Shyam Sundar S K @ 2025-10-17 10:25 UTC (permalink / raw)
To: hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello, Yijun.Shen,
Sanket.Goswami, Shyam Sundar S K
Add a bios_output[] cache to amd_pmf_dev and store the latest values for
BIOS output policies when applying PMF policies. This enables the AMD PMF
util layer to expose these BIOS outputs alongside selected thermal and
power telemetry to user space via /dev/amdpmf_interface and a new IOCTL,
supporting real-time monitoring tools such as SystemDeck.
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/pmf.h | 1 +
drivers/platform/x86/amd/pmf/tee-if.c | 10 ++
drivers/platform/x86/amd/pmf/util.c | 190 ++++++++++++++++++++++++++
3 files changed, 201 insertions(+)
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 3b1aae8a60a5..5880d6fc3afb 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -406,6 +406,7 @@ struct amd_pmf_dev {
struct apmf_sbios_req_v1 req1;
struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */
bool cb_flag; /* To handle first custom BIOS input */
+ u32 bios_output[10];
};
struct apmf_sps_prop_granular_v2 {
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 6e8116bef4f6..8ea309aade95 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -183,42 +183,52 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
break;
case PMF_POLICY_BIOS_OUTPUT_1:
+ dev->bios_output[0] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(0), 0);
break;
case PMF_POLICY_BIOS_OUTPUT_2:
+ dev->bios_output[1] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(1), 1);
break;
case PMF_POLICY_BIOS_OUTPUT_3:
+ dev->bios_output[2] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(2), 2);
break;
case PMF_POLICY_BIOS_OUTPUT_4:
+ dev->bios_output[3] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(3), 3);
break;
case PMF_POLICY_BIOS_OUTPUT_5:
+ dev->bios_output[4] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(4), 4);
break;
case PMF_POLICY_BIOS_OUTPUT_6:
+ dev->bios_output[5] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(5), 5);
break;
case PMF_POLICY_BIOS_OUTPUT_7:
+ dev->bios_output[6] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(6), 6);
break;
case PMF_POLICY_BIOS_OUTPUT_8:
+ dev->bios_output[7] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(7), 7);
break;
case PMF_POLICY_BIOS_OUTPUT_9:
+ dev->bios_output[8] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(8), 8);
break;
case PMF_POLICY_BIOS_OUTPUT_10:
+ dev->bios_output[9] = val;
amd_pmf_smartpc_apply_bios_output(dev, val, BIT(9), 9);
break;
}
diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
index 483e4531535e..307c22791a07 100644
--- a/drivers/platform/x86/amd/pmf/util.c
+++ b/drivers/platform/x86/amd/pmf/util.c
@@ -15,6 +15,7 @@
#include "pmf.h"
#define IOCTL_PMF_QUERY_FEATURE_SUPPORT 0
+#define IOCTL_PMF_GET_METRICS_DATA 38
/* AMD PMF Feature IDs */
#define PMF_FEATURE_AUTO_MODE 0
@@ -25,12 +26,197 @@
#define AMD_PMF_FEATURE_VERSION 0x02
+enum pmf_metrics_id {
+ IOCTL_POWER_SOURCE,
+ IOCTL_POWER_SLIDER_POSITION,
+ IOCTL_PLATFORM_TYPE,
+ IOCTL_LAPTOP_PLACEMENT,
+ IOCTL_LID_STATE,
+ IOCTL_HETERO_STATE,
+ IOCTL_SKIN_TEMP,
+ IOCTL_USER_PRESENCE,
+ IOCTL_DISPLAY_NUM,
+ IOCTL_BATTERY_PERCENTAGE,
+ IOCTL_BIOS_INPUT_1,
+ IOCTL_BIOS_INPUT_2,
+ IOCTL_BIOS_INPUT_3,
+ IOCTL_BIOS_INPUT_4,
+ IOCTL_BIOS_INPUT_5,
+ IOCTL_BIOS_INPUT_6,
+ IOCTL_BIOS_INPUT_7,
+ IOCTL_BIOS_INPUT_8,
+ IOCTL_BIOS_INPUT_9,
+ IOCTL_BIOS_INPUT_10,
+ IOCTL_GFX_WORKLOAD,
+ IOCTL_DESIGNED_BATTERY_CAPACITY = 24,
+ IOCTL_FULLY_CHARGED_BATTERY_CAPACITY,
+ IOCTL_BATTERY_DRAIN_RATE,
+ IOCTL_AMBIENT_LIGHT = 29,
+ IOCTL_AVG_C0_RES = 36,
+ IOCTL_MAX_C0_RES,
+ IOCTL_SOCKET_POWER = 50,
+ IOCTL_TA_BIN_VER,
+ IOCTL_BIOS_OUTPUT_1,
+ IOCTL_BIOS_OUTPUT_2,
+ IOCTL_BIOS_OUTPUT_3,
+ IOCTL_BIOS_OUTPUT_4,
+ IOCTL_BIOS_OUTPUT_5,
+ IOCTL_BIOS_OUTPUT_6,
+ IOCTL_BIOS_OUTPUT_7,
+ IOCTL_BIOS_OUTPUT_8,
+ IOCTL_BIOS_OUTPUT_9,
+ IOCTL_BIOS_OUTPUT_10,
+ IOCTL_MAX,
+};
+
+struct amd_pmf_metrics_key {
+ enum pmf_metrics_id control_code;
+ long long val;
+};
+
struct amd_pmf_feature_support {
bool feature_supported;
unsigned long feature_version;
unsigned long feature_id;
};
+static int amd_pmf_get_metrics_data(struct device *dev, void __user *argp)
+{
+ struct ta_pmf_shared_memory *ta_sm = NULL;
+ struct ta_pmf_enact_table *in = NULL;
+ struct amd_pmf_metrics_key output;
+ struct amd_pmf_dev *pdev;
+
+ pdev = amd_pmf_get_handle();
+ if (!pdev)
+ return -EINVAL;
+
+ memset(pdev->shbuf, 0, pdev->policy_sz);
+ ta_sm = pdev->shbuf;
+ in = &ta_sm->pmf_input.enact_table;
+
+ if (copy_from_user(&output, argp, sizeof(output)))
+ return -EFAULT;
+
+ switch (output.control_code) {
+ case IOCTL_POWER_SOURCE:
+ output.val = in->ev_info.power_source;
+ break;
+ case IOCTL_POWER_SLIDER_POSITION:
+ output.val = in->ev_info.power_slider;
+ break;
+ case IOCTL_PLATFORM_TYPE:
+ output.val = in->ev_info.platform_type;
+ break;
+ case IOCTL_LAPTOP_PLACEMENT:
+ output.val = in->ev_info.device_state;
+ break;
+ case IOCTL_LID_STATE:
+ output.val = in->ev_info.lid_state;
+ break;
+ case IOCTL_SKIN_TEMP:
+ output.val = in->ev_info.skin_temperature / 100;
+ break;
+ case IOCTL_USER_PRESENCE:
+ output.val = in->ev_info.user_present;
+ break;
+ case IOCTL_BATTERY_PERCENTAGE:
+ output.val = in->ev_info.bat_percentage;
+ break;
+ case IOCTL_BIOS_INPUT_1:
+ output.val = in->ev_info.bios_input_1[0];
+ break;
+ case IOCTL_BIOS_INPUT_2:
+ output.val = in->ev_info.bios_input_1[1];
+ break;
+ case IOCTL_BIOS_INPUT_3:
+ output.val = in->ev_info.bios_input_2[0];
+ break;
+ case IOCTL_BIOS_INPUT_4:
+ output.val = in->ev_info.bios_input_2[1];
+ break;
+ case IOCTL_BIOS_INPUT_5:
+ output.val = in->ev_info.bios_input_2[2];
+ break;
+ case IOCTL_BIOS_INPUT_6:
+ output.val = in->ev_info.bios_input_2[3];
+ break;
+ case IOCTL_BIOS_INPUT_7:
+ output.val = in->ev_info.bios_input_2[4];
+ break;
+ case IOCTL_BIOS_INPUT_8:
+ output.val = in->ev_info.bios_input_2[5];
+ break;
+ case IOCTL_BIOS_INPUT_9:
+ output.val = in->ev_info.bios_input_2[6];
+ break;
+ case IOCTL_BIOS_INPUT_10:
+ output.val = in->ev_info.bios_input_2[7];
+ break;
+ case IOCTL_GFX_WORKLOAD:
+ output.val = in->ev_info.gfx_busy;
+ break;
+ case IOCTL_DESIGNED_BATTERY_CAPACITY:
+ output.val = in->ev_info.bat_design;
+ break;
+ case IOCTL_FULLY_CHARGED_BATTERY_CAPACITY:
+ output.val = in->ev_info.full_charge_capacity;
+ break;
+ case IOCTL_BATTERY_DRAIN_RATE:
+ output.val = in->ev_info.drain_rate;
+ break;
+ case IOCTL_AMBIENT_LIGHT:
+ output.val = in->ev_info.ambient_light;
+ break;
+ case IOCTL_AVG_C0_RES:
+ output.val = in->ev_info.avg_c0residency;
+ break;
+ case IOCTL_MAX_C0_RES:
+ output.val = in->ev_info.max_c0residency;
+ break;
+ case IOCTL_SOCKET_POWER:
+ output.val = in->ev_info.socket_power;
+ break;
+ case IOCTL_BIOS_OUTPUT_1:
+ output.val = pdev->bios_output[0];
+ break;
+ case IOCTL_BIOS_OUTPUT_2:
+ output.val = pdev->bios_output[1];
+ break;
+ case IOCTL_BIOS_OUTPUT_3:
+ output.val = pdev->bios_output[2];
+ break;
+ case IOCTL_BIOS_OUTPUT_4:
+ output.val = pdev->bios_output[3];
+ break;
+ case IOCTL_BIOS_OUTPUT_5:
+ output.val = pdev->bios_output[4];
+ break;
+ case IOCTL_BIOS_OUTPUT_6:
+ output.val = pdev->bios_output[5];
+ break;
+ case IOCTL_BIOS_OUTPUT_7:
+ output.val = pdev->bios_output[6];
+ break;
+ case IOCTL_BIOS_OUTPUT_8:
+ output.val = pdev->bios_output[7];
+ break;
+ case IOCTL_BIOS_OUTPUT_9:
+ output.val = pdev->bios_output[8];
+ break;
+ case IOCTL_BIOS_OUTPUT_10:
+ output.val = pdev->bios_output[9];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (copy_to_user(argp, &output, sizeof(output)))
+ return -EFAULT;
+
+ return 0;
+}
+
static int amd_pmf_get_feature_status(void __user *argp, unsigned long feat_id)
{
struct amd_pmf_feature_support info;
@@ -70,6 +256,7 @@ static int amd_pmf_get_feature_status(void __user *argp, unsigned long feat_id)
static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
+ struct device *dev = filp->private_data;
void __user *argp = (void __user *)arg;
struct amd_pmf_feature_support output;
int ret = -ENOTTY;
@@ -82,6 +269,9 @@ static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long
case IOCTL_PMF_QUERY_FEATURE_SUPPORT:
ret = amd_pmf_get_feature_status(argp, output.feature_id);
break;
+ case IOCTL_PMF_GET_METRICS_DATA:
+ ret = amd_pmf_get_metrics_data(dev, argp);
+ break;
default:
return -EINVAL;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] Documentation/ABI: add testing entry for AMD PMF misc device interface
2025-10-17 10:25 [PATCH 0/3] platform/x86/amd/pmf: introduce AMD PMF util layer and user-space interface for SystemDeck Shyam Sundar S K
2025-10-17 10:25 ` [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface Shyam Sundar S K
2025-10-17 10:25 ` [PATCH 2/3] platform/x86/amd/pmf: cache BIOS output values for user-space telemetry via util IOCTL Shyam Sundar S K
@ 2025-10-17 10:25 ` Shyam Sundar S K
2025-10-17 15:24 ` Mario Limonciello
2 siblings, 1 reply; 7+ messages in thread
From: Shyam Sundar S K @ 2025-10-17 10:25 UTC (permalink / raw)
To: hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello, Yijun.Shen,
Sanket.Goswami, Shyam Sundar S K
Add a Documentation/ABI/testing entry describing the AMD PMF util layer
misc device (/dev/amdpmf_interface) and the initial ioctls used to query
feature support and metrics data information. This interface is available
when CONFIG_AMD_PMF_UTIL_SUPPORT=y.
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
.../ABI/testing/misc-amdpmf_interface | 55 +++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 56 insertions(+)
create mode 100644 Documentation/ABI/testing/misc-amdpmf_interface
diff --git a/Documentation/ABI/testing/misc-amdpmf_interface b/Documentation/ABI/testing/misc-amdpmf_interface
new file mode 100644
index 000000000000..c4c7ea68c008
--- /dev/null
+++ b/Documentation/ABI/testing/misc-amdpmf_interface
@@ -0,0 +1,55 @@
+What: /dev/amdpmf_interface
+Date: October 2025
+KernelVersion: 6.x
+Contact: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+Description:
+ The AMD Platform Management Framework (PMF) util layer exposes a
+ minimal user-space interface via a misc character device for
+ feature discovery and metrics monitoring.
+
+ When CONFIG_AMD_PMF_UTIL_SUPPORT is enabled, the driver creates
+ a misc device:
+
+ ======================
+ /dev/amdpmf_interface
+ ======================
+
+ The interface currently supports following ioctls:
+
+ ========================================== =========================================
+ IOCTL Usage
+ IOCTL_PMF_QUERY_FEATURE_SUPPORT (value: 0) User passes a struct amd_pmf_feature_support with feature_id set.
+ The driver returns whether the feature is supported and a version.
+
+ IOCTL_PMF_GET_METRICS_DATA (value: 38) User passes a struct amd_pmf_feature_support with feature_id set.
+ The driver returns the requested metrics data.
+ ========================================== =========================================
+
+ Following are the IOCTL codes supported currently:
+
+ ============ =========================================
+ Feature ID IOCTL Support
+ 0 PMF_FEATURE_AUTO_MODE
+ 2 PMF_FEATURE_STATIC_POWER_SLIDER
+ 4 PMF_FEATURE_POLICY_BUILDER (Smart PC)
+ 5 PMF_FEATURE_DYNAMIC_POWER_SLIDER_AC
+ 6 PMF_FEATURE_DYNAMIC_POWER_SLIDER_DC
+ ============ =========================================
+
+ Following are the return codes:
+
+ ============= =========================================
+ Return code Description
+ 0 success
+ EINVAL feature_id is not recognized, or handle is not available
+ EFAULT copy_to_user/copy_from_user failures
+ ENOTTY unsupported ioctl commands
+ ============= =========================================
+
+ User-space tools integrating with AMD PMF to discover capabilities
+ and monitor metrics data.
+
+Notes:
+ - The ABI is currently considered "testing" and subject to change.
+ - Feature version in the response is currently 0x02.
+ - This interface is only present when CONFIG_AMD_PMF_UTIL_SUPPORT=y.
diff --git a/MAINTAINERS b/MAINTAINERS
index 46126ce2f968..590766bbb10e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1201,6 +1201,7 @@ AMD PMF DRIVER
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
+F: Documentation/ABI/testing/misc-amdpmf_interface
F: Documentation/ABI/testing/sysfs-amd-pmf
F: drivers/platform/x86/amd/pmf/
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface
2025-10-17 10:25 ` [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface Shyam Sundar S K
@ 2025-10-17 15:10 ` Mario Limonciello
0 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello @ 2025-10-17 15:10 UTC (permalink / raw)
To: Shyam Sundar S K, hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, Yijun.Shen, Sanket.Goswami
On 10/17/2025 5:25 AM, Shyam Sundar S K wrote:
> Add a util layer to AMD PMF that exposes a minimal user-space interface
> via a misc character device for metrics monitoring and feature discovery.
> This creates /dev/amdpmf_interface with a basic ioctl to report support
> for PMF features (Smart PC Builder, Auto Mode, Static Power Slider,
> Dynamic Power Slider AC/DC), enabling smoother integration with
> user-space tools such as AMD SystemDeck[1].
>
> AMD SystemDeck is a widely used user-space tool for monitoring and
> controlling power and thermal behavior. It helps designers keep major
> components within their thermal limits to ensure proper operation.
> Maintaining temperatures within specification enhances overall system
> stability and reliability.
>
> [1] https://docs.amd.com/v/u/en-US/68773_0.50
This should be
Link: https://docs.amd.com/v/u/en-US/68773_0.50 [1]
>
> Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
> Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
> drivers/platform/x86/amd/pmf/Kconfig | 10 +++
> drivers/platform/x86/amd/pmf/Makefile | 2 +
> drivers/platform/x86/amd/pmf/core.c | 19 +++++
> drivers/platform/x86/amd/pmf/pmf.h | 10 +++
> drivers/platform/x86/amd/pmf/util.c | 115 ++++++++++++++++++++++++++
> 5 files changed, 156 insertions(+)
> create mode 100644 drivers/platform/x86/amd/pmf/util.c
>
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 25b8f7ae3abd..81ea4934e199 100644
> --- a/drivers/platform/x86/amd/pmf/Kconfig
> +++ b/drivers/platform/x86/amd/pmf/Kconfig
> @@ -30,3 +30,13 @@ config AMD_PMF_DEBUG
> in the PMF config store.
>
> Say Y here to enable more debug logs and Say N here if you are not sure.
> +
> +config AMD_PMF_UTIL_SUPPORT
> + bool "AMD PMF Util layer support"
> + depends on AMD_PMF
> + help
> + Enabling this option permits the driver to interface with user
> + space for capturing AMD PMF metrics and updating them to the
> + user space tool for smooth monitoring.
> +
> + Say Y here to enable it and Say N here if you are not sure.
> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> index 5978464e0eb7..bf7aad80b9e9 100644
> --- a/drivers/platform/x86/amd/pmf/Makefile
> +++ b/drivers/platform/x86/amd/pmf/Makefile
> @@ -8,3 +8,5 @@ obj-$(CONFIG_AMD_PMF) += amd-pmf.o
> amd-pmf-y := core.o acpi.o sps.o \
> auto-mode.o cnqf.o \
> tee-if.o spc.o
> +# Build util.c only when AMD_PMF_UTIL_SUPPORT is enabled
> +amd-pmf-$(CONFIG_AMD_PMF_UTIL_SUPPORT) += util.o
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index bc544a4a5266..ac2b80db019e 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -53,6 +53,19 @@ static bool force_load;
> module_param(force_load, bool, 0444);
> MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
>
> +#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
> +struct amd_pmf_dev *pmf_handle;
> +
> +struct amd_pmf_dev *amd_pmf_get_handle(void)
> +{
> + struct amd_pmf_dev *pmf = pmf_handle;
> +
> + return pmf;
> +}
> +#else
> +struct amd_pmf_dev *amd_pmf_get_handle(void) { return NULL; }
> +#endif
> +
> static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
> {
> struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
> @@ -465,6 +478,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
> if (!dev->regbase)
> return -ENOMEM;
>
> +#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
> + pmf_handle = dev;
> +#endif
> +
> mutex_init(&dev->lock);
> mutex_init(&dev->update_mutex);
> mutex_init(&dev->cb_mutex);
> @@ -477,6 +494,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
> if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
> amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD);
>
> + amd_pmf_cdev_register();
> dev_info(dev->dev, "registered PMF device successfully\n");
>
> return 0;
> @@ -489,6 +507,7 @@ static void amd_pmf_remove(struct platform_device *pdev)
> amd_pmf_deinit_features(dev);
> if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
> amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_UNLOAD);
> + amd_pmf_cdev_unregister();
> apmf_acpi_deinit(dev);
> amd_pmf_dbgfs_unregister(dev);
> mutex_destroy(&dev->lock);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index bd19f2a6bc78..3b1aae8a60a5 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -823,6 +823,7 @@ struct ta_pmf_shared_memory {
> };
>
> /* Core Layer */
> +struct amd_pmf_dev *amd_pmf_get_handle(void);
> int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
> void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
> int is_apmf_func_supported(struct amd_pmf_dev *pdev, unsigned long index);
> @@ -888,4 +889,13 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
> void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
> int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev);
>
> +/* Util Layer */
> +#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
> +int amd_pmf_cdev_register(void);
> +void amd_pmf_cdev_unregister(void);
> +#else
> +static inline int amd_pmf_cdev_register(void) { return 0; }
> +static inline void amd_pmf_cdev_unregister(void) {}
> +#endif
> +
> #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
> new file mode 100644
> index 000000000000..483e4531535e
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/util.c
> @@ -0,0 +1,115 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * AMD Platform Management Framework Util Layer
> + *
> + * Copyright (c) 2025, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> + * Sanket Goswami <Sanket.Goswami@amd.com>
> + */
> +
> +#include <linux/miscdevice.h>
> +#include <linux/uaccess.h>
> +
> +#include "pmf.h"
> +
> +#define IOCTL_PMF_QUERY_FEATURE_SUPPORT 0
> +
> +/* AMD PMF Feature IDs */
> +#define PMF_FEATURE_AUTO_MODE 0
> +#define PMF_FEATURE_STATIC_POWER_SLIDER 2
> +#define PMF_FEATURE_POLICY_BUILDER 4
> +#define PMF_FEATURE_DYNAMIC_POWER_SLIDER_AC 5
> +#define PMF_FEATURE_DYNAMIC_POWER_SLIDER_DC 6
> +
> +#define AMD_PMF_FEATURE_VERSION 0x02
> +
> +struct amd_pmf_feature_support {
> + bool feature_supported;
> + unsigned long feature_version;
> + unsigned long feature_id;
> +};
> +
> +static int amd_pmf_get_feature_status(void __user *argp, unsigned long feat_id)
> +{
> + struct amd_pmf_feature_support info;
As nothing populates feature_id, I think you should explicitly
initialize this structure so garbage doesn't get passed back. If all
the commands in the future will reply with AMD_PMF_FEATURE_VERSION
identically you can set it here too when initializing the structure.
> + struct amd_pmf_dev *pdev;
> +
> + pdev = amd_pmf_get_handle();
> + if (!pdev)
> + return -EINVAL;
> +
> + switch (feat_id) {
> + case PMF_FEATURE_AUTO_MODE:
> + info.feature_supported = is_apmf_func_supported(pdev, APMF_FUNC_AUTO_MODE);
> + break;
> + case PMF_FEATURE_STATIC_POWER_SLIDER:
> + info.feature_supported = is_apmf_func_supported(pdev,
> + APMF_FUNC_STATIC_SLIDER_GRANULAR);
> + break;
> + case PMF_FEATURE_POLICY_BUILDER:
> + info.feature_supported = pdev->smart_pc_enabled;
> + break;
> + case PMF_FEATURE_DYNAMIC_POWER_SLIDER_AC:
> + info.feature_supported = is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_AC);
> + break;
> + case PMF_FEATURE_DYNAMIC_POWER_SLIDER_DC:
> + info.feature_supported = is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_DC);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + info.feature_version = AMD_PMF_FEATURE_VERSION;
> + if (copy_to_user(argp, &info, sizeof(info)))
> + return -EFAULT;
> +
> + return 0;
> +}
> +
> +static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> +{
> + void __user *argp = (void __user *)arg;
> + struct amd_pmf_feature_support output;
> + int ret = -ENOTTY;
I don't see a need to initialize ret here when you set it on the next line.
> +
> + ret = copy_from_user(&output, argp, sizeof(output));
> + if (ret)
> + return -EFAULT;
Shouldn't you return ret here? If you always want to return -EFAULT and
throw it away you should instead do:
if (copy_from_user())
return -EFAULT;
> +
> + switch (cmd) {
> + case IOCTL_PMF_QUERY_FEATURE_SUPPORT:
> + ret = amd_pmf_get_feature_status(argp, output.feature_id);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return ret;
If you're not planning on doing any other processing for future commands
you can just instead do this:
switch (cmd) {
case foo:
return bar();
default:
return -EINVAL;
}
}
> +}
> +
> +static const struct file_operations pmf_if_ops = {
> + .unlocked_ioctl = amd_pmf_set_ioctl,
> +};
> +
> +#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
> +static struct miscdevice amd_pmf_util_if = {
> + .minor = MISC_DYNAMIC_MINOR,
> + .name = "amdpmf_interface",
> + .fops = &pmf_if_ops,
> +};
> +
> +int amd_pmf_cdev_register(void)
> +{
> + return misc_register(&amd_pmf_util_if);
> +}
> +
> +void amd_pmf_cdev_unregister(void)
> +{
> + misc_deregister(&amd_pmf_util_if);
> +}
> +#else
> +int amd_pmf_cdev_register(void) { return 0; }
> +void amd_pmf_cdev_unregister(void) {}
> +#endif
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] platform/x86/amd/pmf: cache BIOS output values for user-space telemetry via util IOCTL
2025-10-17 10:25 ` [PATCH 2/3] platform/x86/amd/pmf: cache BIOS output values for user-space telemetry via util IOCTL Shyam Sundar S K
@ 2025-10-17 15:17 ` Mario Limonciello
0 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello @ 2025-10-17 15:17 UTC (permalink / raw)
To: Shyam Sundar S K, hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, Yijun.Shen, Sanket.Goswami
On 10/17/2025 5:25 AM, Shyam Sundar S K wrote:
> Add a bios_output[] cache to amd_pmf_dev and store the latest values for
> BIOS output policies when applying PMF policies. This enables the AMD PMF
> util layer to expose these BIOS outputs alongside selected thermal and
> power telemetry to user space via /dev/amdpmf_interface and a new IOCTL,
> supporting real-time monitoring tools such as SystemDeck.
>
> Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
> Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
One comment below though.
> ---
> drivers/platform/x86/amd/pmf/pmf.h | 1 +
> drivers/platform/x86/amd/pmf/tee-if.c | 10 ++
> drivers/platform/x86/amd/pmf/util.c | 190 ++++++++++++++++++++++++++
> 3 files changed, 201 insertions(+)
>
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 3b1aae8a60a5..5880d6fc3afb 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -406,6 +406,7 @@ struct amd_pmf_dev {
> struct apmf_sbios_req_v1 req1;
> struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */
> bool cb_flag; /* To handle first custom BIOS input */
> + u32 bios_output[10];
> };
>
> struct apmf_sps_prop_granular_v2 {
> diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
> index 6e8116bef4f6..8ea309aade95 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -183,42 +183,52 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_1:
> + dev->bios_output[0] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(0), 0);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_2:
> + dev->bios_output[1] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(1), 1);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_3:
> + dev->bios_output[2] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(2), 2);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_4:
> + dev->bios_output[3] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(3), 3);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_5:
> + dev->bios_output[4] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(4), 4);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_6:
> + dev->bios_output[5] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(5), 5);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_7:
> + dev->bios_output[6] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(6), 6);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_8:
> + dev->bios_output[7] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(7), 7);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_9:
> + dev->bios_output[8] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(8), 8);
> break;
>
> case PMF_POLICY_BIOS_OUTPUT_10:
> + dev->bios_output[9] = val;
> amd_pmf_smartpc_apply_bios_output(dev, val, BIT(9), 9);
> break;
> }
> diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
> index 483e4531535e..307c22791a07 100644
> --- a/drivers/platform/x86/amd/pmf/util.c
> +++ b/drivers/platform/x86/amd/pmf/util.c
> @@ -15,6 +15,7 @@
> #include "pmf.h"
>
> #define IOCTL_PMF_QUERY_FEATURE_SUPPORT 0
> +#define IOCTL_PMF_GET_METRICS_DATA 38
>
> /* AMD PMF Feature IDs */
> #define PMF_FEATURE_AUTO_MODE 0
> @@ -25,12 +26,197 @@
>
> #define AMD_PMF_FEATURE_VERSION 0x02
>
> +enum pmf_metrics_id {
> + IOCTL_POWER_SOURCE,
> + IOCTL_POWER_SLIDER_POSITION,
> + IOCTL_PLATFORM_TYPE,
> + IOCTL_LAPTOP_PLACEMENT,
> + IOCTL_LID_STATE,
> + IOCTL_HETERO_STATE,
> + IOCTL_SKIN_TEMP,
> + IOCTL_USER_PRESENCE,
> + IOCTL_DISPLAY_NUM,
> + IOCTL_BATTERY_PERCENTAGE,
> + IOCTL_BIOS_INPUT_1,
> + IOCTL_BIOS_INPUT_2,
> + IOCTL_BIOS_INPUT_3,
> + IOCTL_BIOS_INPUT_4,
> + IOCTL_BIOS_INPUT_5,
> + IOCTL_BIOS_INPUT_6,
> + IOCTL_BIOS_INPUT_7,
> + IOCTL_BIOS_INPUT_8,
> + IOCTL_BIOS_INPUT_9,
> + IOCTL_BIOS_INPUT_10,
> + IOCTL_GFX_WORKLOAD,
> + IOCTL_DESIGNED_BATTERY_CAPACITY = 24,
> + IOCTL_FULLY_CHARGED_BATTERY_CAPACITY,
> + IOCTL_BATTERY_DRAIN_RATE,
> + IOCTL_AMBIENT_LIGHT = 29,
> + IOCTL_AVG_C0_RES = 36,
> + IOCTL_MAX_C0_RES,
> + IOCTL_SOCKET_POWER = 50,
> + IOCTL_TA_BIN_VER,
> + IOCTL_BIOS_OUTPUT_1,
> + IOCTL_BIOS_OUTPUT_2,
> + IOCTL_BIOS_OUTPUT_3,
> + IOCTL_BIOS_OUTPUT_4,
> + IOCTL_BIOS_OUTPUT_5,
> + IOCTL_BIOS_OUTPUT_6,
> + IOCTL_BIOS_OUTPUT_7,
> + IOCTL_BIOS_OUTPUT_8,
> + IOCTL_BIOS_OUTPUT_9,
> + IOCTL_BIOS_OUTPUT_10,
> + IOCTL_MAX,
I don't think you need IOCTL_MAX, do you?
> +};
> +
> +struct amd_pmf_metrics_key {
> + enum pmf_metrics_id control_code;
> + long long val;
> +};
> +
> struct amd_pmf_feature_support {
> bool feature_supported;
> unsigned long feature_version;
> unsigned long feature_id;
> };
>
> +static int amd_pmf_get_metrics_data(struct device *dev, void __user *argp)
> +{
> + struct ta_pmf_shared_memory *ta_sm = NULL;
> + struct ta_pmf_enact_table *in = NULL;
> + struct amd_pmf_metrics_key output;
> + struct amd_pmf_dev *pdev;
> +
> + pdev = amd_pmf_get_handle();
> + if (!pdev)
> + return -EINVAL;
> +
> + memset(pdev->shbuf, 0, pdev->policy_sz);
> + ta_sm = pdev->shbuf;
> + in = &ta_sm->pmf_input.enact_table;
> +
> + if (copy_from_user(&output, argp, sizeof(output)))
> + return -EFAULT;
> +
> + switch (output.control_code) {
> + case IOCTL_POWER_SOURCE:
> + output.val = in->ev_info.power_source;
> + break;
> + case IOCTL_POWER_SLIDER_POSITION:
> + output.val = in->ev_info.power_slider;
> + break;
> + case IOCTL_PLATFORM_TYPE:
> + output.val = in->ev_info.platform_type;
> + break;
> + case IOCTL_LAPTOP_PLACEMENT:
> + output.val = in->ev_info.device_state;
> + break;
> + case IOCTL_LID_STATE:
> + output.val = in->ev_info.lid_state;
> + break;
> + case IOCTL_SKIN_TEMP:
> + output.val = in->ev_info.skin_temperature / 100;
> + break;
> + case IOCTL_USER_PRESENCE:
> + output.val = in->ev_info.user_present;
> + break;
> + case IOCTL_BATTERY_PERCENTAGE:
> + output.val = in->ev_info.bat_percentage;
> + break;
> + case IOCTL_BIOS_INPUT_1:
> + output.val = in->ev_info.bios_input_1[0];
> + break;
> + case IOCTL_BIOS_INPUT_2:
> + output.val = in->ev_info.bios_input_1[1];
> + break;
> + case IOCTL_BIOS_INPUT_3:
> + output.val = in->ev_info.bios_input_2[0];
> + break;
> + case IOCTL_BIOS_INPUT_4:
> + output.val = in->ev_info.bios_input_2[1];
> + break;
> + case IOCTL_BIOS_INPUT_5:
> + output.val = in->ev_info.bios_input_2[2];
> + break;
> + case IOCTL_BIOS_INPUT_6:
> + output.val = in->ev_info.bios_input_2[3];
> + break;
> + case IOCTL_BIOS_INPUT_7:
> + output.val = in->ev_info.bios_input_2[4];
> + break;
> + case IOCTL_BIOS_INPUT_8:
> + output.val = in->ev_info.bios_input_2[5];
> + break;
> + case IOCTL_BIOS_INPUT_9:
> + output.val = in->ev_info.bios_input_2[6];
> + break;
> + case IOCTL_BIOS_INPUT_10:
> + output.val = in->ev_info.bios_input_2[7];
> + break;
> + case IOCTL_GFX_WORKLOAD:
> + output.val = in->ev_info.gfx_busy;
> + break;
> + case IOCTL_DESIGNED_BATTERY_CAPACITY:
> + output.val = in->ev_info.bat_design;
> + break;
> + case IOCTL_FULLY_CHARGED_BATTERY_CAPACITY:
> + output.val = in->ev_info.full_charge_capacity;
> + break;
> + case IOCTL_BATTERY_DRAIN_RATE:
> + output.val = in->ev_info.drain_rate;
> + break;
> + case IOCTL_AMBIENT_LIGHT:
> + output.val = in->ev_info.ambient_light;
> + break;
> + case IOCTL_AVG_C0_RES:
> + output.val = in->ev_info.avg_c0residency;
> + break;
> + case IOCTL_MAX_C0_RES:
> + output.val = in->ev_info.max_c0residency;
> + break;
> + case IOCTL_SOCKET_POWER:
> + output.val = in->ev_info.socket_power;
> + break;
> + case IOCTL_BIOS_OUTPUT_1:
> + output.val = pdev->bios_output[0];
> + break;
> + case IOCTL_BIOS_OUTPUT_2:
> + output.val = pdev->bios_output[1];
> + break;
> + case IOCTL_BIOS_OUTPUT_3:
> + output.val = pdev->bios_output[2];
> + break;
> + case IOCTL_BIOS_OUTPUT_4:
> + output.val = pdev->bios_output[3];
> + break;
> + case IOCTL_BIOS_OUTPUT_5:
> + output.val = pdev->bios_output[4];
> + break;
> + case IOCTL_BIOS_OUTPUT_6:
> + output.val = pdev->bios_output[5];
> + break;
> + case IOCTL_BIOS_OUTPUT_7:
> + output.val = pdev->bios_output[6];
> + break;
> + case IOCTL_BIOS_OUTPUT_8:
> + output.val = pdev->bios_output[7];
> + break;
> + case IOCTL_BIOS_OUTPUT_9:
> + output.val = pdev->bios_output[8];
> + break;
> + case IOCTL_BIOS_OUTPUT_10:
> + output.val = pdev->bios_output[9];
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + if (copy_to_user(argp, &output, sizeof(output)))
> + return -EFAULT;
> +
> + return 0;
> +}
> +
> static int amd_pmf_get_feature_status(void __user *argp, unsigned long feat_id)
> {
> struct amd_pmf_feature_support info;
> @@ -70,6 +256,7 @@ static int amd_pmf_get_feature_status(void __user *argp, unsigned long feat_id)
>
> static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> {
> + struct device *dev = filp->private_data;
> void __user *argp = (void __user *)arg;
> struct amd_pmf_feature_support output;
> int ret = -ENOTTY;
> @@ -82,6 +269,9 @@ static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long
> case IOCTL_PMF_QUERY_FEATURE_SUPPORT:
> ret = amd_pmf_get_feature_status(argp, output.feature_id);
> break;
> + case IOCTL_PMF_GET_METRICS_DATA:
> + ret = amd_pmf_get_metrics_data(dev, argp);
> + break;
> default:
> return -EINVAL;
> }
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] Documentation/ABI: add testing entry for AMD PMF misc device interface
2025-10-17 10:25 ` [PATCH 3/3] Documentation/ABI: add testing entry for AMD PMF misc device interface Shyam Sundar S K
@ 2025-10-17 15:24 ` Mario Limonciello
0 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello @ 2025-10-17 15:24 UTC (permalink / raw)
To: Shyam Sundar S K, hdegoede, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, Yijun.Shen, Sanket.Goswami
On 10/17/2025 5:25 AM, Shyam Sundar S K wrote:
> Add a Documentation/ABI/testing entry describing the AMD PMF util layer
> misc device (/dev/amdpmf_interface) and the initial ioctls used to query
> feature support and metrics data information. This interface is available
> when CONFIG_AMD_PMF_UTIL_SUPPORT=y.
>
> Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
> Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
> .../ABI/testing/misc-amdpmf_interface | 55 +++++++++++++++++++
> MAINTAINERS | 1 +
> 2 files changed, 56 insertions(+)
> create mode 100644 Documentation/ABI/testing/misc-amdpmf_interface
>
> diff --git a/Documentation/ABI/testing/misc-amdpmf_interface b/Documentation/ABI/testing/misc-amdpmf_interface
> new file mode 100644
> index 000000000000..c4c7ea68c008
> --- /dev/null
> +++ b/Documentation/ABI/testing/misc-amdpmf_interface
> @@ -0,0 +1,55 @@
> +What: /dev/amdpmf_interface
> +Date: October 2025
This should be 6.19+ material now, so should push out later.
> +KernelVersion: 6.x
> +Contact: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> +Description:
> + The AMD Platform Management Framework (PMF) util layer exposes a
> + minimal user-space interface via a misc character device for
> + feature discovery and metrics monitoring.
> +
> + When CONFIG_AMD_PMF_UTIL_SUPPORT is enabled, the driver creates
> + a misc device:
> +
> + ======================
> + /dev/amdpmf_interface
> + ======================
> +
> + The interface currently supports following ioctls:
> +
> + ========================================== =========================================
> + IOCTL Usage
> + IOCTL_PMF_QUERY_FEATURE_SUPPORT (value: 0) User passes a struct amd_pmf_feature_support with feature_id set.
> + The driver returns whether the feature is supported and a version.
> +
> + IOCTL_PMF_GET_METRICS_DATA (value: 38) User passes a struct amd_pmf_feature_support with feature_id set.
> + The driver returns the requested metrics data.
> + ========================================== =========================================
> +
> + Following are the IOCTL codes supported currently:
> +
> + ============ =========================================
> + Feature ID IOCTL Support
> + 0 PMF_FEATURE_AUTO_MODE
> + 2 PMF_FEATURE_STATIC_POWER_SLIDER
> + 4 PMF_FEATURE_POLICY_BUILDER (Smart PC)
> + 5 PMF_FEATURE_DYNAMIC_POWER_SLIDER_AC
> + 6 PMF_FEATURE_DYNAMIC_POWER_SLIDER_DC
> + ============ =========================================
> +
> + Following are the return codes:
> +
> + ============= =========================================
> + Return code Description
> + 0 success
> + EINVAL feature_id is not recognized, or handle is not available
> + EFAULT copy_to_user/copy_from_user failures
> + ENOTTY unsupported ioctl commands
> + ============= =========================================
> +
> + User-space tools integrating with AMD PMF to discover capabilities
> + and monitor metrics data.
> +
> +Notes:
> + - The ABI is currently considered "testing" and subject to change.
> + - Feature version in the response is currently 0x02.
> + - This interface is only present when CONFIG_AMD_PMF_UTIL_SUPPORT=y.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 46126ce2f968..590766bbb10e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1201,6 +1201,7 @@ AMD PMF DRIVER
> M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> L: platform-driver-x86@vger.kernel.org
> S: Supported
> +F: Documentation/ABI/testing/misc-amdpmf_interface
> F: Documentation/ABI/testing/sysfs-amd-pmf
> F: drivers/platform/x86/amd/pmf/
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-10-17 15:24 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-17 10:25 [PATCH 0/3] platform/x86/amd/pmf: introduce AMD PMF util layer and user-space interface for SystemDeck Shyam Sundar S K
2025-10-17 10:25 ` [PATCH 1/3] platform/x86/amd/pmf: add util layer and user-space misc device interface Shyam Sundar S K
2025-10-17 15:10 ` Mario Limonciello
2025-10-17 10:25 ` [PATCH 2/3] platform/x86/amd/pmf: cache BIOS output values for user-space telemetry via util IOCTL Shyam Sundar S K
2025-10-17 15:17 ` Mario Limonciello
2025-10-17 10:25 ` [PATCH 3/3] Documentation/ABI: add testing entry for AMD PMF misc device interface Shyam Sundar S K
2025-10-17 15:24 ` Mario Limonciello
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).