* [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface
@ 2026-05-20 18:54 Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface Shyam Sundar S K
` (7 more replies)
0 siblings, 8 replies; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
This patch series introduces a new util layer for the AMD Platform
Management Framework (PMF) driver that exposes a minimal userspace
interface for metrics monitoring and feature discovery.
AMD PMF currently manages power and thermal policies internally through
Smart PC features, Auto Mode, Policy Builder, Static/Dynamic Power
Sliders. However, system designers and OEMs need visibility into PMF
metrics and feature status for validation, debugging, and integration
with monitoring tools.
This series addresses that need by adding a character device interface
that allows controlled access to PMF metrics data while maintaining
the driver's existing automated policy management.
The primary use case is integration with userspace tools like AMD
SystemDeck, which are widely used by system designers to:
- Monitor real-time power and thermal behavior
- Validate PMF feature operation during platform bring-up
- Debug thermal issues by tracking skin temperature, C-state residency,
and socket power metrics
- Verify BIOS input/output policy values during Smart PC operation
The util layer reads from the existing Trusted Application (TA) shared
memory buffer and cached BIOS output values, adding no new communication
overhead with the TA.
v5:
- Add actual ioctl implementation after all struct fields are defined
- Move features_supported field just after size for early discovery
- Add 8-byte alignment check for user_size to prevent odd-byte copies
- Add AMD_PMF prefix to all UAPI enum names to avoid namespace collisions
- Use size_t for loop variable instead of int with cast
- Use ternary operator for checkbox output
- Add empty line before Linux kernel headers
- Refactor banner to const char * for cleaner formatting
v4:
- Implement single amd_pmf_info structure which can cover all members.
- Add amd_pmf prefix for enums/functions within the UAPI header.
- Keep test-pmf tool outside of selftests directory.
- Include necessary header files.
- Address review comments received from Ilpo on v3.
v3:
- Stop exporting battery information via util layer.
- Optimize the core logic for fetching BIOS outputs.
- Update the documentation patch to reflect the current util layer design.
- Consolidate amd-pmf-io.h changes into common UAPI header.
- Define a single unified uAPI structure and IOCTL.
- Address other v2 review remarks [1]
v2:
- address remarks from v1
- add a new tool that exercises the IOCTLs from PMF interface
[1] https://lore.kernel.org/platform-driver-x86/20251111071010.4179492-1-
Shyam-sundar.S-k@amd.com/
Shyam Sundar S K (8):
platform/x86/amd/pmf: Add util layer and userspace character device
interface
platform/x86/amd/pmf: store BIOS output values for user-space metrics
via util IOCTL
platform/x86/amd/pmf: Add feature discovery support to util interface
platform/x86/amd/pmf: Store commonly used enums in the header file
platform/x86/amd/pmf: Move debug helper functions to UAPI header
platform/x86/amd/pmf: Implement util layer ioctl handler
platform/x86/amd/pmf: Introduce AMD PMF testing tool for driver
metrics and features
Documentation/ABI: add testing entry for AMD PMF character device
interface
Documentation/ABI/testing/amdpmf-interface | 74 +++++++
MAINTAINERS | 1 +
.../amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 13 +-
drivers/platform/x86/amd/pmf/Kconfig | 10 +
drivers/platform/x86/amd/pmf/Makefile | 2 +
drivers/platform/x86/amd/pmf/core.c | 5 +
drivers/platform/x86/amd/pmf/pmf.h | 33 +--
drivers/platform/x86/amd/pmf/spc.c | 68 +-----
drivers/platform/x86/amd/pmf/tee-if.c | 11 +-
drivers/platform/x86/amd/pmf/util.c | 155 ++++++++++++++
include/linux/amd-pmf-io.h | 9 -
include/uapi/linux/amd-pmf.h | 202 ++++++++++++++++++
tools/platform/x86/amd/Makefile | 60 ++++++
tools/platform/x86/amd/test-pmf.c | 142 ++++++++++++
14 files changed, 686 insertions(+), 99 deletions(-)
create mode 100644 Documentation/ABI/testing/amdpmf-interface
create mode 100644 drivers/platform/x86/amd/pmf/util.c
create mode 100644 include/uapi/linux/amd-pmf.h
create mode 100644 tools/platform/x86/amd/Makefile
create mode 100644 tools/platform/x86/amd/test-pmf.c
--
2.34.1
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-22 13:21 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 2/8] platform/x86/amd/pmf: store BIOS output values for user-space metrics via util IOCTL Shyam Sundar S K
` (6 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
Add a util layer to AMD PMF that exposes a minimal userspace interface
via a character device for metrics monitoring and feature discovery.
This creates /dev/amdpmf_interface with basic ioctl support to retrieve
PMF metrics such as:
* Power source and power slider position
* Platform type, lid state, and user presence
* Skin temperature and ambient light
* BIOS input parameters (1-10)
* Graphics workload metrics
* CPU C-state residency (average and maximum)
* Socket power consumption
The interface enables smoother integration with userspace tools such as
AMD SystemDeck [1], which is widely used for monitoring and controlling
power and thermal behavior on AMD platforms. These tools help designers
keep major components within thermal limits to ensure proper operation
and enhance overall system stability and reliability.
The feature is gated behind the CONFIG_AMD_PMF_UTIL_SUPPORT Kconfig
option, allowing it to be disabled if not needed. The implementation
uses existing PMF infrastructure to populate data from the TA (Trusted
Application) shared memory buffer.
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 | 5 ++
drivers/platform/x86/amd/pmf/pmf.h | 9 ++++
drivers/platform/x86/amd/pmf/util.c | 67 +++++++++++++++++++++++++++
include/uapi/linux/amd-pmf.h | 60 ++++++++++++++++++++++++
6 files changed, 153 insertions(+)
create mode 100644 drivers/platform/x86/amd/pmf/util.c
create mode 100644 include/uapi/linux/amd-pmf.h
diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index 25b8f7ae3abd..ad4faf18de47 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 provides a character device for userspace to capture
+ PMF features (Smart PC Builder, Auto Mode, Static Power Slider, Dynamic
+ Power Slider AC/DC) along with PMF metrics from the AMD PMF driver.
+
+ 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 b9e5a2cf3aae..919d02f30aae 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -634,6 +634,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
pmf_device = dev->dev;
+ err = amd_pmf_cdev_register(dev);
+ if (err)
+ dev_warn(dev->dev, "failed to register util interface: %d\n", err);
+
dev_info(dev->dev, "registered PMF device successfully\n");
return 0;
@@ -646,6 +650,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);
}
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 69fef7448744..6f61076a9386 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -928,4 +928,13 @@ int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid);
void amd_pmf_tee_deinit(struct amd_pmf_dev *dev);
int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev);
+/* Util Layer */
+#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
+int amd_pmf_cdev_register(struct amd_pmf_dev *dev);
+void amd_pmf_cdev_unregister(void);
+#else
+static inline int amd_pmf_cdev_register(struct amd_pmf_dev *dev) { 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..0052f0b6a7a5
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/util.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Platform Management Framework Util Layer
+ *
+ * Copyright (c) 2026, 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/amd-pmf.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+
+#include "pmf.h"
+
+static struct amd_pmf_dev *pmf_dev_handle;
+static DEFINE_MUTEX(pmf_util_lock);
+
+static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ return -ENOTTY;
+}
+
+static int amd_pmf_open(struct inode *inode, struct file *filp)
+{
+ guard(mutex)(&pmf_util_lock);
+ if (!pmf_dev_handle)
+ return -ENODEV;
+
+ filp->private_data = pmf_dev_handle;
+ return 0;
+}
+
+static const struct file_operations pmf_if_ops = {
+ .owner = THIS_MODULE,
+ .open = amd_pmf_open,
+ .unlocked_ioctl = amd_pmf_set_ioctl,
+};
+
+static struct miscdevice amd_pmf_util_if = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "amdpmf_interface",
+ .fops = &pmf_if_ops,
+};
+
+int amd_pmf_cdev_register(struct amd_pmf_dev *dev)
+{
+ int ret;
+
+ guard(mutex)(&pmf_util_lock);
+ pmf_dev_handle = dev;
+ ret = misc_register(&amd_pmf_util_if);
+ if (ret)
+ pmf_dev_handle = NULL;
+
+ return ret;
+}
+
+void amd_pmf_cdev_unregister(void)
+{
+ guard(mutex)(&pmf_util_lock);
+ misc_deregister(&amd_pmf_util_if);
+ pmf_dev_handle = NULL;
+}
diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
new file mode 100644
index 000000000000..c7099e7f463f
--- /dev/null
+++ b/include/uapi/linux/amd-pmf.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
+/*
+ * AMD Platform Management Framework (PMF) UAPI Header
+ *
+ * Copyright (c) 2026, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * This file defines the user-space API for interacting with the AMD PMF
+ * driver. It provides ioctl interfaces to query platform-specific metrics
+ * such as power source, slider position, platform type, laptop placement,
+ * and various BIOS input/output parameters.
+ */
+
+#ifndef _UAPI_LINUX_AMD_PMF_H
+#define _UAPI_LINUX_AMD_PMF_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * AMD_PMF_IOC_MAGIC - Magic number for AMD PMF ioctl commands
+ *
+ * This magic number uniquely identifies AMD PMF ioctl operations.
+ */
+#define AMD_PMF_IOC_MAGIC 'p'
+
+/**
+ * IOCTL_AMD_PMF_POPULATE_DATA - ioctl command to retrieve PMF metrics data
+ *
+ * This ioctl command is used to populate the amd_pmf_info structure
+ * with the requested PMF metrics information.
+ */
+#define IOCTL_AMD_PMF_POPULATE_DATA _IOWR(AMD_PMF_IOC_MAGIC, 0x00, struct amd_pmf_info)
+
+#define AMD_PMF_BIOS_PARAMS_MAX 10
+
+struct amd_pmf_info {
+ __u64 size;
+
+ /* Power and state info */
+ __u32 platform_type;
+ __u32 power_source;
+ __u32 laptop_placement;
+ __u32 lid_state;
+ __u32 user_presence;
+ __u32 slider_position;
+
+ /* Thermal and power metrics */
+ __s32 skin_temp;
+ __u32 gfx_busy;
+ __s32 ambient_light;
+ __u32 avg_c0_residency;
+ __u32 max_c0_residency;
+ __u32 socket_power;
+
+ /* BIOS parameters */
+ __u32 bios_input[AMD_PMF_BIOS_PARAMS_MAX];
+};
+
+#endif /* _UAPI_LINUX_AMD_PMF_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 2/8] platform/x86/amd/pmf: store BIOS output values for user-space metrics via util IOCTL
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-22 13:28 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 3/8] platform/x86/amd/pmf: Add feature discovery support to util interface Shyam Sundar S K
` (5 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
Add a bios_output[] to amd_pmf_dev struct 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 metrics 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 | 2 ++
drivers/platform/x86/amd/pmf/tee-if.c | 11 ++++++++++-
include/uapi/linux/amd-pmf.h | 1 +
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 6f61076a9386..ffe74ebc46f8 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -130,6 +130,7 @@ struct cookie_header {
#define GET_CMD true
#define METRICS_TABLE_ID 7
+#define BIOS_OUTPUT_MAX 10
typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data);
@@ -442,6 +443,7 @@ struct amd_pmf_dev {
struct pmf_cbi_ring_buffer cbi_buf;
struct mutex cbi_mutex; /* Protects ring buffer access */
struct mutex metrics_mutex;
+ u32 bios_output[BIOS_OUTPUT_MAX];
};
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 7ccd93f506b2..be8062c6691d 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -8,7 +8,9 @@
* Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
*/
+#include <linux/array_size.h>
#include <linux/debugfs.h>
+#include <linux/dev_printk.h>
#include <linux/tee_drv.h>
#include <linux/uuid.h>
#include "pmf.h"
@@ -98,10 +100,17 @@ static int amd_pmf_get_bios_output_idx(u32 action_idx)
static void amd_pmf_update_bios_output(struct amd_pmf_dev *pdev, struct ta_pmf_action *action)
{
u32 bios_idx;
+ int ret;
bios_idx = amd_pmf_get_bios_output_idx(action->action_index);
+ if (bios_idx >= ARRAY_SIZE(pdev->bios_output)) {
+ dev_warn(pdev->dev, "BIOS output index %u out of bounds\n", bios_idx);
+ return;
+ }
- amd_pmf_smartpc_apply_bios_output(pdev, action->value, BIT(bios_idx), bios_idx);
+ ret = amd_pmf_smartpc_apply_bios_output(pdev, action->value, BIT(bios_idx), bios_idx);
+ if (!ret)
+ pdev->bios_output[bios_idx] = action->value;
}
static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
index c7099e7f463f..d29a4abe1145 100644
--- a/include/uapi/linux/amd-pmf.h
+++ b/include/uapi/linux/amd-pmf.h
@@ -55,6 +55,7 @@ struct amd_pmf_info {
/* BIOS parameters */
__u32 bios_input[AMD_PMF_BIOS_PARAMS_MAX];
+ __u32 bios_output[AMD_PMF_BIOS_PARAMS_MAX];
};
#endif /* _UAPI_LINUX_AMD_PMF_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 3/8] platform/x86/amd/pmf: Add feature discovery support to util interface
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 2/8] platform/x86/amd/pmf: store BIOS output values for user-space metrics via util IOCTL Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-22 13:29 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 4/8] platform/x86/amd/pmf: Store commonly used enums in the header file Shyam Sundar S K
` (4 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
Add feature discovery capability to the util layer interface, allowing
userspace tools to query which PMF features are supported and enabled
on the current platform.
The following features can now be queried through the
/dev/amdpmf_interface ioctl:
* Auto Mode: Automatic power profile switching based on system activity
* Static Power Slider: User-selectable power profiles
* Policy Builder (Smart PC): Action based policy management
* Dynamic Power Slider AC: Adaptive power profiles when on AC power
* Dynamic Power Slider DC: Adaptive power profiles when on battery
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>
---
include/uapi/linux/amd-pmf.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
index d29a4abe1145..38ab5362fe62 100644
--- a/include/uapi/linux/amd-pmf.h
+++ b/include/uapi/linux/amd-pmf.h
@@ -34,9 +34,19 @@
#define AMD_PMF_BIOS_PARAMS_MAX 10
+/* AMD PMF feature flags - bitmask indicating supported features */
+#define AMD_PMF_FEAT_AUTO_MODE BIT(0)
+#define AMD_PMF_FEAT_STATIC_POWER_SLIDER BIT(1)
+#define AMD_PMF_FEAT_POLICY_BUILDER BIT(2)
+#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC BIT(3)
+#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC BIT(4)
+
struct amd_pmf_info {
__u64 size;
+ /* Feature info */
+ __u32 features_supported;
+
/* Power and state info */
__u32 platform_type;
__u32 power_source;
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 4/8] platform/x86/amd/pmf: Store commonly used enums in the header file
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
` (2 preceding siblings ...)
2026-05-20 18:54 ` [PATCH v5 3/8] platform/x86/amd/pmf: Add feature discovery support to util interface Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-22 13:31 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header Shyam Sundar S K
` (3 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
Relocate commonly used enums from multiple source files into a shared
header file to simplify code structure, improve readability, and
enhance maintainability. Also, remove the initialization of the first
enum member, since it is not needed.
Add the AMD_PMF_ prefix to the laptop_placement and platform_type enums
since these names are overly generic for inclusion in a UAPI header
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>
---
.../amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 13 ++--
drivers/platform/x86/amd/pmf/pmf.h | 22 ------
drivers/platform/x86/amd/pmf/spc.c | 37 +++++-----
include/linux/amd-pmf-io.h | 9 ---
include/uapi/linux/amd-pmf.h | 74 +++++++++++++++++++
5 files changed, 100 insertions(+), 55 deletions(-)
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index 837d59e7a661..8ac44368a37d 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -7,6 +7,7 @@
*
* Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
*/
+#include <linux/amd-pmf.h>
#include <linux/amd-pmf-io.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/iopoll.h>
@@ -102,20 +103,20 @@ static int amd_sfh_mode_info(u32 *platform_type, u32 *laptop_placement)
*platform_type = mode.op_mode.devicemode;
if (mode.op_mode.ontablestate == 1) {
- *laptop_placement = ON_TABLE;
+ *laptop_placement = AMD_PMF_ON_TABLE;
} else if (mode.op_mode.ontablestate == 2) {
- *laptop_placement = ON_LAP_MOTION;
+ *laptop_placement = AMD_PMF_ON_LAP_MOTION;
} else if (mode.op_mode.inbagstate == 1) {
- *laptop_placement = IN_BAG;
+ *laptop_placement = AMD_PMF_IN_BAG;
} else if (mode.op_mode.outbagstate == 1) {
- *laptop_placement = OUT_OF_BAG;
+ *laptop_placement = AMD_PMF_OUT_OF_BAG;
} else if (mode.op_mode.ontablestate == 0 || mode.op_mode.inbagstate == 0 ||
mode.op_mode.outbagstate == 0) {
- *laptop_placement = LP_UNKNOWN;
+ *laptop_placement = AMD_PMF_LP_UNKNOWN;
pr_warn_once("Unknown laptop placement\n");
} else if (mode.op_mode.ontablestate == 3 || mode.op_mode.inbagstate == 3 ||
mode.op_mode.outbagstate == 3) {
- *laptop_placement = LP_UNDEFINED;
+ *laptop_placement = AMD_PMF_LP_UNDEFINED;
pr_warn_once("Undefined laptop placement\n");
}
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index ffe74ebc46f8..269c0a4b1cae 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -682,14 +682,6 @@ enum system_state {
SYSTEM_STATE_MAX,
};
-enum ta_slider {
- TA_BEST_BATTERY,
- TA_BETTER_BATTERY,
- TA_BETTER_PERFORMANCE,
- TA_BEST_PERFORMANCE,
- TA_MAX,
-};
-
struct amd_pmf_pb_bitmap {
const char *name;
u32 bit_mask;
@@ -721,20 +713,6 @@ static const struct amd_pmf_pb_bitmap custom_bios_inputs_v1[] __used = {
{"NOTIFY_CUSTOM_BIOS_INPUT10", BIT(16)},
};
-enum platform_type {
- PTYPE_UNKNOWN = 0,
- LID_CLOSE,
- CLAMSHELL,
- FLAT,
- TENT,
- STAND,
- TABLET,
- BOOK,
- PRESENTATION,
- PULL_FWD,
- PTYPE_INVALID = 0xf,
-};
-
/* Command ids for TA communication */
enum ta_pmf_command {
TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE,
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index f48678a23cc7..05998946d1bd 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -10,6 +10,7 @@
*/
#include <acpi/button.h>
+#include <linux/amd-pmf.h>
#include <linux/amd-pmf-io.h>
#include <linux/cleanup.h>
#include <linux/power_supply.h>
@@ -20,21 +21,21 @@
static const char *platform_type_as_str(u16 platform_type)
{
switch (platform_type) {
- case CLAMSHELL:
+ case AMD_PMF_CLAMSHELL:
return "CLAMSHELL";
- case FLAT:
+ case AMD_PMF_FLAT:
return "FLAT";
- case TENT:
+ case AMD_PMF_TENT:
return "TENT";
- case STAND:
+ case AMD_PMF_STAND:
return "STAND";
- case TABLET:
+ case AMD_PMF_TABLET:
return "TABLET";
- case BOOK:
+ case AMD_PMF_BOOK:
return "BOOK";
- case PRESENTATION:
+ case AMD_PMF_PRESENTATION:
return "PRESENTATION";
- case PULL_FWD:
+ case AMD_PMF_PULL_FWD:
return "PULL_FWD";
default:
return "UNKNOWN";
@@ -44,13 +45,13 @@ static const char *platform_type_as_str(u16 platform_type)
static const char *laptop_placement_as_str(u16 device_state)
{
switch (device_state) {
- case ON_TABLE:
+ case AMD_PMF_ON_TABLE:
return "ON_TABLE";
- case ON_LAP_MOTION:
+ case AMD_PMF_ON_LAP_MOTION:
return "ON_LAP_MOTION";
- case IN_BAG:
+ case AMD_PMF_IN_BAG:
return "IN_BAG";
- case OUT_OF_BAG:
+ case AMD_PMF_OUT_OF_BAG:
return "OUT_OF_BAG";
default:
return "UNKNOWN";
@@ -60,11 +61,11 @@ static const char *laptop_placement_as_str(u16 device_state)
static const char *ta_slider_as_str(unsigned int state)
{
switch (state) {
- case TA_BEST_PERFORMANCE:
+ case AMD_PMF_TA_BEST_PERFORMANCE:
return "PERFORMANCE";
- case TA_BETTER_PERFORMANCE:
+ case AMD_PMF_TA_BETTER_PERFORMANCE:
return "BALANCED";
- case TA_BEST_BATTERY:
+ case AMD_PMF_TA_BEST_BATTERY:
return "POWER_SAVER";
default:
return "Unknown TA Slider State";
@@ -287,14 +288,14 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_
switch (dev->current_profile) {
case PLATFORM_PROFILE_PERFORMANCE:
case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
- val = TA_BEST_PERFORMANCE;
+ val = AMD_PMF_TA_BEST_PERFORMANCE;
break;
case PLATFORM_PROFILE_BALANCED:
- val = TA_BETTER_PERFORMANCE;
+ val = AMD_PMF_TA_BETTER_PERFORMANCE;
break;
case PLATFORM_PROFILE_LOW_POWER:
case PLATFORM_PROFILE_QUIET:
- val = TA_BEST_BATTERY;
+ val = AMD_PMF_TA_BEST_BATTERY;
break;
default:
dev_err(dev->dev, "Unknown Platform Profile.\n");
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
index 55198d2875cc..e014d4ce5a20 100644
--- a/include/linux/amd-pmf-io.h
+++ b/include/linux/amd-pmf-io.h
@@ -52,15 +52,6 @@ struct amd_sfh_info {
u32 laptop_placement;
};
-enum laptop_placement {
- LP_UNKNOWN = 0,
- ON_TABLE,
- ON_LAP_MOTION,
- IN_BAG,
- OUT_OF_BAG,
- LP_UNDEFINED,
-};
-
/**
* struct amd_pmf_npu_metrics: Get NPU metrics data from PMF driver
* @npuclk_freq: NPU clock frequency [MHz]
diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
index 38ab5362fe62..54baf015e4c1 100644
--- a/include/uapi/linux/amd-pmf.h
+++ b/include/uapi/linux/amd-pmf.h
@@ -41,6 +41,80 @@
#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC BIT(3)
#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC BIT(4)
+/**
+ * enum laptop_placement - Describes the physical placement of the laptop
+ * @AMD_PMF_LP_UNKNOWN: Placement cannot be determined
+ * @AMD_PMF_ON_TABLE: Laptop is placed on a stable surface like a table or desk
+ * @AMD_PMF_ON_LAP_MOTION: Laptop is on a lap with detected motion
+ * @AMD_PMF_IN_BAG: Laptop is detected to be inside a bag or case
+ * @AMD_PMF_OUT_OF_BAG: Laptop has been removed from bag or case
+ * @AMD_PMF_LP_UNDEFINED: Placement state is undefined
+ *
+ * This enumeration represents the physical placement state of the laptop
+ * as detected by platform sensors. Used for adaptive power management
+ * and thermal policies.
+ */
+enum amd_pmf_laptop_placement {
+ AMD_PMF_LP_UNKNOWN,
+ AMD_PMF_ON_TABLE,
+ AMD_PMF_ON_LAP_MOTION,
+ AMD_PMF_IN_BAG,
+ AMD_PMF_OUT_OF_BAG,
+ AMD_PMF_LP_UNDEFINED,
+};
+
+/**
+ * enum ta_slider - Trusted Application power slider positions
+ * @AMD_PMF_TA_BEST_BATTERY: Maximum battery savings, minimal performance
+ * @AMD_PMF_TA_BETTER_BATTERY: Balanced towards battery life
+ * @AMD_PMF_TA_BETTER_PERFORMANCE: Balanced towards performance
+ * @AMD_PMF_TA_BEST_PERFORMANCE: Maximum performance, higher power consumption
+ * @AMD_PMF_TA_MAX: Sentinel value indicating maximum enum value
+ *
+ * This enumeration defines the power slider positions used by the
+ * AMD PMF Trusted Application for dynamic power management decisions.
+ * These correspond to the Windows power slider UI positions.
+ */
+enum amd_pmf_ta_slider {
+ AMD_PMF_TA_BEST_BATTERY,
+ AMD_PMF_TA_BETTER_BATTERY,
+ AMD_PMF_TA_BETTER_PERFORMANCE,
+ AMD_PMF_TA_BEST_PERFORMANCE,
+ AMD_PMF_TA_MAX,
+};
+
+/**
+ * enum platform_type - Describes the physical form factor orientation
+ * @AMD_PMF_PTYPE_UNKNOWN: Platform type cannot be determined
+ * @AMD_PMF_LID_CLOSE: Laptop lid is closed
+ * @AMD_PMF_CLAMSHELL: Traditional laptop mode with keyboard and screen
+ * @AMD_PMF_FLAT: Device is lying flat on a surface
+ * @AMD_PMF_TENT: Device is in tent mode (keyboard folded back, standing)
+ * @AMD_PMF_STAND: Device is propped up in stand orientation
+ * @AMD_PMF_TABLET: Device is in tablet mode with keyboard hidden
+ * @AMD_PMF_BOOK: Device is in book reading orientation
+ * @AMD_PMF_PRESENTATION: Device is in presentation mode
+ * @AMD_PMF_PULL_FWD: Screen is pulled forward towards user
+ * @AMD_PMF_PTYPE_INVALID: Invalid platform type marker
+ *
+ * This enumeration describes the current physical orientation or form
+ * factor of convertible/2-in-1 devices. Used for optimizing power and
+ * thermal management based on device posture.
+ */
+enum amd_pmf_platform_type {
+ AMD_PMF_PTYPE_UNKNOWN,
+ AMD_PMF_LID_CLOSE,
+ AMD_PMF_CLAMSHELL,
+ AMD_PMF_FLAT,
+ AMD_PMF_TENT,
+ AMD_PMF_STAND,
+ AMD_PMF_TABLET,
+ AMD_PMF_BOOK,
+ AMD_PMF_PRESENTATION,
+ AMD_PMF_PULL_FWD,
+ AMD_PMF_PTYPE_INVALID = 0xf,
+};
+
struct amd_pmf_info {
__u64 size;
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
` (3 preceding siblings ...)
2026-05-20 18:54 ` [PATCH v5 4/8] platform/x86/amd/pmf: Store commonly used enums in the header file Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-21 11:02 ` Ilpo Järvinen
2026-05-22 13:35 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler Shyam Sundar S K
` (2 subsequent siblings)
7 siblings, 2 replies; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
These debug helper functions convert enumerated values to appropriate
message and can be useful for userspace tools and other kernel components
that need to interpret AMD PMF state values.
By making them inline functions in the UAPI header, they become available
to both kernel and userspace without code duplication. Also, prefix the
function names with amd_pmf_.
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/spc.c | 61 ++----------------------------
include/uapi/linux/amd-pmf.h | 57 ++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 58 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index 05998946d1bd..0606d3b0adde 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -18,60 +18,6 @@
#include "pmf.h"
#ifdef CONFIG_AMD_PMF_DEBUG
-static const char *platform_type_as_str(u16 platform_type)
-{
- switch (platform_type) {
- case AMD_PMF_CLAMSHELL:
- return "CLAMSHELL";
- case AMD_PMF_FLAT:
- return "FLAT";
- case AMD_PMF_TENT:
- return "TENT";
- case AMD_PMF_STAND:
- return "STAND";
- case AMD_PMF_TABLET:
- return "TABLET";
- case AMD_PMF_BOOK:
- return "BOOK";
- case AMD_PMF_PRESENTATION:
- return "PRESENTATION";
- case AMD_PMF_PULL_FWD:
- return "PULL_FWD";
- default:
- return "UNKNOWN";
- }
-}
-
-static const char *laptop_placement_as_str(u16 device_state)
-{
- switch (device_state) {
- case AMD_PMF_ON_TABLE:
- return "ON_TABLE";
- case AMD_PMF_ON_LAP_MOTION:
- return "ON_LAP_MOTION";
- case AMD_PMF_IN_BAG:
- return "IN_BAG";
- case AMD_PMF_OUT_OF_BAG:
- return "OUT_OF_BAG";
- default:
- return "UNKNOWN";
- }
-}
-
-static const char *ta_slider_as_str(unsigned int state)
-{
- switch (state) {
- case AMD_PMF_TA_BEST_PERFORMANCE:
- return "PERFORMANCE";
- case AMD_PMF_TA_BETTER_PERFORMANCE:
- return "BALANCED";
- case AMD_PMF_TA_BEST_BATTERY:
- return "POWER_SAVER";
- default:
- return "Unknown TA Slider State";
- }
-}
-
static u32 amd_pmf_get_ta_custom_bios_inputs(struct ta_pmf_enact_table *in, int index)
{
switch (index) {
@@ -89,7 +35,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
int i;
dev_dbg(dev->dev, "==== TA inputs START ====\n");
- dev_dbg(dev->dev, "Slider State: %s\n", ta_slider_as_str(in->ev_info.power_slider));
+ dev_dbg(dev->dev, "Slider State: %s\n", amd_pmf_get_sp(in->ev_info.power_slider));
dev_dbg(dev->dev, "Power Source: %s\n", amd_pmf_source_as_str(in->ev_info.power_source));
dev_dbg(dev->dev, "Battery Percentage: %u\n", in->ev_info.bat_percentage);
dev_dbg(dev->dev, "Designed Battery Capacity: %u\n", in->ev_info.bat_design);
@@ -103,9 +49,8 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
dev_dbg(dev->dev, "LID State: %s\n", in->ev_info.lid_state ? "close" : "open");
dev_dbg(dev->dev, "User Presence: %s\n", in->ev_info.user_present ? "Present" : "Away");
dev_dbg(dev->dev, "Ambient Light: %d\n", in->ev_info.ambient_light);
- dev_dbg(dev->dev, "Platform type: %s\n", platform_type_as_str(in->ev_info.platform_type));
- dev_dbg(dev->dev, "Laptop placement: %s\n",
- laptop_placement_as_str(in->ev_info.device_state));
+ dev_dbg(dev->dev, "Platform type: %s\n", amd_pmf_get_pt(in->ev_info.platform_type));
+ dev_dbg(dev->dev, "Laptop placement: %s\n", amd_pmf_get_lp(in->ev_info.device_state));
for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
dev_dbg(dev->dev, "Custom BIOS input%d: %u\n", i + 1,
amd_pmf_get_ta_custom_bios_inputs(in, i));
diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
index 54baf015e4c1..a8c715bee9cc 100644
--- a/include/uapi/linux/amd-pmf.h
+++ b/include/uapi/linux/amd-pmf.h
@@ -115,6 +115,63 @@ enum amd_pmf_platform_type {
AMD_PMF_PTYPE_INVALID = 0xf,
};
+/* Retrieve the platform type as a string */
+static inline const char *amd_pmf_get_pt(unsigned int platform_type)
+{
+ switch (platform_type) {
+ case AMD_PMF_CLAMSHELL:
+ return "CLAMSHELL";
+ case AMD_PMF_FLAT:
+ return "FLAT";
+ case AMD_PMF_TENT:
+ return "TENT";
+ case AMD_PMF_STAND:
+ return "STAND";
+ case AMD_PMF_TABLET:
+ return "TABLET";
+ case AMD_PMF_BOOK:
+ return "BOOK";
+ case AMD_PMF_PRESENTATION:
+ return "PRESENTATION";
+ case AMD_PMF_PULL_FWD:
+ return "PULL_FWD";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/* Retrieve the laptop placement as a string */
+static inline const char *amd_pmf_get_lp(unsigned int device_state)
+{
+ switch (device_state) {
+ case AMD_PMF_ON_TABLE:
+ return "ON_TABLE";
+ case AMD_PMF_ON_LAP_MOTION:
+ return "ON_LAP_MOTION";
+ case AMD_PMF_IN_BAG:
+ return "IN_BAG";
+ case AMD_PMF_OUT_OF_BAG:
+ return "OUT_OF_BAG";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/* Retrieve the slider position as a string */
+static inline const char *amd_pmf_get_sp(unsigned int state)
+{
+ switch (state) {
+ case AMD_PMF_TA_BEST_PERFORMANCE:
+ return "PERFORMANCE";
+ case AMD_PMF_TA_BETTER_PERFORMANCE:
+ return "BALANCED";
+ case AMD_PMF_TA_BEST_BATTERY:
+ return "POWER_SAVER";
+ default:
+ return "Unknown TA Slider State";
+ }
+}
+
struct amd_pmf_info {
__u64 size;
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
` (4 preceding siblings ...)
2026-05-20 18:54 ` [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-21 10:58 ` Ilpo Järvinen
2026-05-22 13:44 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 7/8] platform/x86/amd/pmf: Introduce AMD PMF testing tool for driver metrics and features Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface Shyam Sundar S K
7 siblings, 2 replies; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
Implement the ioctl handler for the util layer character device. This
support adds the actual functionality to populate PMF metrics from the
TA shared memory buffer and return them to userspace.
The implementation includes:
- amd_pmf_populate_data() to extract metrics from TA shared memory
- amd_pmf_set_ioctl() to handle userspace ioctl requests
- Size negotiation for forward/backward compatibility
- Feature-based population of struct fields
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/util.c | 90 ++++++++++++++++++++++++++++-
1 file changed, 89 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
index 0052f0b6a7a5..eb9a02e135a9 100644
--- a/drivers/platform/x86/amd/pmf/util.c
+++ b/drivers/platform/x86/amd/pmf/util.c
@@ -19,9 +19,97 @@
static struct amd_pmf_dev *pmf_dev_handle;
static DEFINE_MUTEX(pmf_util_lock);
+static int amd_pmf_populate_data(struct amd_pmf_dev *pdev, struct amd_pmf_info *info)
+{
+ struct ta_pmf_shared_memory *ta_sm = NULL;
+ struct ta_pmf_enact_table *in = NULL;
+ int idx;
+
+ if (!pdev || !info)
+ return -EINVAL;
+
+ ta_sm = pdev->shbuf;
+ in = &ta_sm->pmf_input.enact_table;
+
+ /* Set size and version */
+ info->size = sizeof(struct amd_pmf_info);
+
+ /* PMF Feature support flags */
+ if (is_apmf_func_supported(pdev, APMF_FUNC_AUTO_MODE))
+ info->features_supported |= AMD_PMF_FEAT_AUTO_MODE;
+ if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+ info->features_supported |= AMD_PMF_FEAT_STATIC_POWER_SLIDER;
+ if (pdev->smart_pc_enabled)
+ info->features_supported |= AMD_PMF_FEAT_POLICY_BUILDER;
+ if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_AC))
+ info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC;
+ if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_DC))
+ info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC;
+
+ /* Device States */
+ info->platform_type = in->ev_info.platform_type;
+ info->laptop_placement = in->ev_info.device_state;
+ info->lid_state = in->ev_info.lid_state;
+ info->user_presence = in->ev_info.user_present;
+ info->slider_position = in->ev_info.power_slider;
+
+ /* Thermal and Power Metrics */
+ info->power_source = in->ev_info.power_source;
+ info->skin_temp = in->ev_info.skin_temperature;
+ info->gfx_busy = in->ev_info.gfx_busy;
+ info->ambient_light = in->ev_info.ambient_light;
+ info->avg_c0_residency = in->ev_info.avg_c0residency;
+ info->max_c0_residency = in->ev_info.max_c0residency;
+ info->socket_power = in->ev_info.socket_power;
+
+ /* Custom BIOS input parameters */
+ for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++) {
+ if (idx < 2)
+ info->bios_input[idx] = in->ev_info.bios_input_1[idx];
+ else
+ info->bios_input[idx] = in->ev_info.bios_input_2[idx - 2];
+ }
+
+ /* BIOS output parameters */
+ for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++)
+ info->bios_output[idx] = pdev->bios_output[idx];
+
+ return 0;
+}
+
static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- return -ENOTTY;
+ struct amd_pmf_dev *pdev = filp->private_data;
+ void __user *argp = (void __user *)arg;
+ struct amd_pmf_info info = {};
+ size_t copy_size;
+ __u64 user_size;
+ int ret;
+
+ if (cmd != IOCTL_AMD_PMF_POPULATE_DATA)
+ return -ENOTTY;
+
+ /* First read just the size field from userspace */
+ if (copy_from_user(&user_size, argp, sizeof(user_size)))
+ return -EFAULT;
+
+ if (user_size & (sizeof(__u64) - 1))
+ return -EINVAL;
+
+ guard(mutex)(&pmf_util_lock);
+ ret = amd_pmf_populate_data(pdev, &info);
+ if (ret)
+ return ret;
+
+ copy_size = min_t(size_t, user_size, sizeof(struct amd_pmf_info));
+
+ /* Set actual size being copied */
+ info.size = copy_size;
+
+ if (copy_to_user(argp, &info, copy_size))
+ return -EFAULT;
+
+ return 0;
}
static int amd_pmf_open(struct inode *inode, struct file *filp)
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 7/8] platform/x86/amd/pmf: Introduce AMD PMF testing tool for driver metrics and features
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
` (5 preceding siblings ...)
2026-05-20 18:54 ` [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface Shyam Sundar S K
7 siblings, 0 replies; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
This tool leverages amd-pmf ioctls exposed via the util layer, allowing
validation of its newly integrated util layer and /dev/amdpmf_interface.
It includes a user-space test application, test_amd_pmf, designed to
interact with the PMF driver and retrieve relevant metrics for the
testing and analysis.
It provides definitions for test metrics, feature IDs, and device states,
and includes tests for various AMD PMF metrics such as power source, skin
temperature, battery state, and custom BIOS inputs/outputs. It also
enables the testing of PMF metrics data and feature support reporting.
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>
---
tools/platform/x86/amd/Makefile | 60 +++++++++++++
tools/platform/x86/amd/test-pmf.c | 142 ++++++++++++++++++++++++++++++
2 files changed, 202 insertions(+)
create mode 100644 tools/platform/x86/amd/Makefile
create mode 100644 tools/platform/x86/amd/test-pmf.c
diff --git a/tools/platform/x86/amd/Makefile b/tools/platform/x86/amd/Makefile
new file mode 100644
index 000000000000..5d820df5871f
--- /dev/null
+++ b/tools/platform/x86/amd/Makefile
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+endif
+
+# Include common tools build infrastructure
+include $(srctree)/tools/scripts/Makefile.include
+
+CC = $(CROSS_COMPILE)gcc
+BUILD_OUTPUT := $(CURDIR)
+PREFIX ?= /usr
+DESTDIR ?=
+
+ifeq ("$(origin O)", "command line")
+ BUILD_OUTPUT := $(O)
+endif
+
+# Include paths: tools/include has linux/kernel.h with ARRAY_SIZE
+INCLUDES = -I$(srctree)/tools/include
+INCLUDES += -I$(srctree)/tools/include/uapi
+INCLUDES += -I$(srctree)/include/uapi
+INCLUDES += -I$(srctree)/include
+
+override CFLAGS += -O2 -Wall -Wextra -D_GNU_SOURCE $(INCLUDES)
+override CFLAGS += -D_FILE_OFFSET_BITS=64
+override CFLAGS += -D__EXPORTED_HEADERS__
+
+TARGETS = test_amd_pmf
+
+all: $(TARGETS)
+
+test_amd_pmf: test-pmf.c
+ $(QUIET_CC)$(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS)
+
+.PHONY: clean
+clean:
+ $(call QUIET_CLEAN, test_amd_pmf)$(RM) $(BUILD_OUTPUT)/test_amd_pmf
+
+.PHONY: install
+install: $(TARGETS)
+ $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) $(BUILD_OUTPUT)/test_amd_pmf $(DESTDIR)$(PREFIX)/bin/test_amd_pmf
+
+.PHONY: help
+help:
+ @echo "AMD Platform Tools Makefile"
+ @echo ""
+ @echo "Targets:"
+ @echo " all - Build all tools (default)"
+ @echo " test_amd_pmf - Build the PMF test tool"
+ @echo " clean - Remove built files"
+ @echo " install - Install tools to $(PREFIX)/bin"
+ @echo ""
+ @echo "Variables:"
+ @echo " O=<dir> - Build output directory"
+ @echo " PREFIX - Installation prefix (default: /usr)"
+ @echo " DESTDIR - Destination directory for install"
diff --git a/tools/platform/x86/amd/test-pmf.c b/tools/platform/x86/amd/test-pmf.c
new file mode 100644
index 000000000000..313e952189dc
--- /dev/null
+++ b/tools/platform/x86/amd/test-pmf.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Platform Management Framework Test Tool
+ *
+ * Copyright (c) 2026, 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 <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <linux/amd-pmf.h>
+#include <linux/kernel.h>
+
+#define DEVICE_NODE "/dev/amdpmf_interface"
+
+/* Feature flag names */
+static const char * const feature_names[] = {
+ "Auto Mode",
+ "Static Power Slider",
+ "Policy Builder (Smart PC)",
+ "Dynamic Power Slider AC",
+ "Dynamic Power Slider DC",
+};
+
+static const char *banner =
+ "====================================================\n"
+ " AMD PMF Metrics info and Feature Status\n"
+ "====================================================\n\n";
+
+/* Print feature flags */
+static void pmf_print_features(uint32_t flags)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(feature_names); i++)
+ printf(" [%c] %s\n", (flags & (1U << i)) ? 'x' : ' ', feature_names[i]);
+}
+
+/* Print BIOS parameters */
+static void pmf_print_bios_params(const char *type, const __u32 *params)
+{
+ int i;
+
+ for (i = 0; i < AMD_PMF_BIOS_PARAMS_MAX; i++)
+ printf(" Custom BIOS %s%d: %u\n", type, i + 1, params[i]);
+}
+
+/* Open the PMF device */
+static int pmf_open_device(void)
+{
+ int fd;
+
+ fd = open(DEVICE_NODE, O_RDONLY);
+ if (fd < 0)
+ fprintf(stderr, "Error: Cannot open %s: %s\n", DEVICE_NODE, strerror(errno));
+
+ return fd;
+}
+
+/* Query PMF info using the single IOCTL */
+static int pmf_get_info(int fd, struct amd_pmf_info *info)
+{
+ int ret;
+
+ /* Zero-initialize and set size for versioning */
+ memset(info, 0, sizeof(*info));
+ info->size = sizeof(*info);
+
+ ret = ioctl(fd, IOCTL_AMD_PMF_POPULATE_DATA, info);
+ if (ret < 0) {
+ fprintf(stderr, "Error: IOCTL_AMD_PMF_POPULATE_DATA failed: %s\n", strerror(errno));
+ return ret;
+ }
+
+ return 0;
+}
+
+static void pmf_print_info(const struct amd_pmf_info *info)
+{
+ printf("%s", banner);
+
+ /* Feature status */
+ printf("Feature Status:\n");
+ pmf_print_features(info->features_supported);
+
+ /* Device states */
+ printf("\nDevice States:\n");
+ printf(" Platform Type: %s\n", amd_pmf_get_pt(info->platform_type));
+ printf(" Laptop Placement: %s\n", amd_pmf_get_lp(info->laptop_placement));
+ printf(" Lid State: %s\n", info->lid_state ? "Closed" : "Open");
+ printf(" User Presence: %s\n", info->user_presence ? "Present" : "Away");
+ printf(" Slider Position: %s\n", amd_pmf_get_sp(info->slider_position));
+
+ /* Thermal and power metrics */
+ printf("\nThermal/Power Metrics:\n");
+ printf(" Skin Temperature: %d\n", info->skin_temp / 100);
+ printf(" GFX Busy: %u\n", info->gfx_busy);
+ printf(" Ambient Light: %d\n", info->ambient_light);
+ printf(" Avg C0 Residency: %u\n", info->avg_c0_residency);
+ printf(" Max C0 Residency: %u\n", info->max_c0_residency);
+ printf(" Socket Power: %u\n", info->socket_power);
+
+ /* BIOS parameters */
+ printf("\nCustom BIOS Input Parameters:\n");
+ pmf_print_bios_params("Input", info->bios_input);
+ printf("\nCustom BIOS Output Parameters:\n");
+ pmf_print_bios_params("Output", info->bios_output);
+
+ printf("\n=================================================\n");
+}
+
+int main(void)
+{
+ struct amd_pmf_info info;
+ int fd, ret;
+
+ fd = pmf_open_device();
+ if (fd < 0)
+ return -1;
+
+ /* Query all info with single IOCTL */
+ ret = pmf_get_info(fd, &info);
+ close(fd);
+
+ if (ret < 0)
+ return -1;
+
+ pmf_print_info(&info);
+
+ return 0;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
` (6 preceding siblings ...)
2026-05-20 18:54 ` [PATCH v5 7/8] platform/x86/amd/pmf: Introduce AMD PMF testing tool for driver metrics and features Shyam Sundar S K
@ 2026-05-20 18:54 ` Shyam Sundar S K
2026-05-21 11:07 ` Ilpo Järvinen
7 siblings, 1 reply; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-20 18:54 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, mario.limonciello, Sanket.Goswami,
Shyam Sundar S K
Add a Documentation/ABI/testing entry describing the AMD PMF util layer
character 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.
Also update the MAINTAINERS record with the new UAPI header.
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
Documentation/ABI/testing/amdpmf-interface | 74 ++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 75 insertions(+)
create mode 100644 Documentation/ABI/testing/amdpmf-interface
diff --git a/Documentation/ABI/testing/amdpmf-interface b/Documentation/ABI/testing/amdpmf-interface
new file mode 100644
index 000000000000..45606907f7e6
--- /dev/null
+++ b/Documentation/ABI/testing/amdpmf-interface
@@ -0,0 +1,74 @@
+What: /dev/amdpmf_interface
+Date: June 2026
+KernelVersion: 7.2
+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 character device for feature
+ discovery and metrics monitoring.
+
+ When CONFIG_AMD_PMF_UTIL_SUPPORT is enabled, the driver creates
+ a character device:
+
+ ======================
+ /dev/amdpmf_interface
+ ======================
+
+ The interface supports a single ioctl:
+
+ ============================ =======================================
+ IOCTL Usage
+ IOCTL_AMD_PMF_POPULATE_DATA User passes a struct amd_pmf_info with
+ the size field set to sizeof(struct
+ amd_pmf_info). The driver returns all
+ available metrics and feature status
+ in the structure.
+ ============================ =======================================
+
+ struct amd_pmf_info layout:
+
+ ======================= ========== ================================
+ Field Type Description
+ size __u64 Structure size for versioning
+ features_version __u32 IOCTL interface version
+ features_supported __u32 Bitmask of supported features
+ platform_type __u32 Platform form factor orientation
+ power_source __u32 AC/DC power source
+ laptop_placement __u32 Device placement state
+ lid_state __u32 Lid open/closed status
+ user_presence __u32 User presence detection
+ slider_position __u32 Current power slider position
+ skin_temp __s32 Skin temperature (centidegrees)
+ gfx_busy __u32 Graphics workload percentage
+ ambient_light __s32 Ambient light sensor reading
+ avg_c0_residency __u32 Average C0 state residency
+ max_c0_residency __u32 Maximum C0 state residency
+ socket_power __u32 Socket power consumption
+ bios_input[10] __u32 Custom BIOS input parameters
+ bios_output[10] __u32 Custom BIOS output parameters
+ ======================= ========== ================================
+
+ Feature Support Flags (features_supported bitmask):
+
+ ===================================== ==== =============================
+ Flag Bit Description
+ AMD_PMF_FEAT_AUTO_MODE 0 Auto Mode feature support
+ AMD_PMF_FEAT_STATIC_POWER_SLIDER 1 Static Power Slider support
+ AMD_PMF_FEAT_POLICY_BUILDER 2 Policy Builder (Smart PC)
+ AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC 3 Dynamic slider on AC
+ AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC 4 Dynamic slider on DC
+ ===================================== ==== =============================
+
+ Return codes:
+
+ ============= ============================================================
+ Return code Description
+ 0 Success
+ EINVAL Invalid size or parameter
+ EFAULT copy_to_user/copy_from_user failures
+ ENODEV PMF device not available
+ ENOTTY Unknown ioctl command
+ ============= ============================================================
+
+ User-space tools integrating with AMD PMF to discover capabilities and
+ monitor real-time metrics for thermal and power management validation.
diff --git a/MAINTAINERS b/MAINTAINERS
index 839e39825455..ec061cd127b2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1216,6 +1216,7 @@ L: platform-driver-x86@vger.kernel.org
S: Supported
F: Documentation/ABI/testing/sysfs-amd-pmf
F: drivers/platform/x86/amd/pmf/
+F: include/uapi/linux/amd-pmf.h
AMD POWERPLAY AND SWSMU
M: Kenneth Feng <kenneth.feng@amd.com>
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler
2026-05-20 18:54 ` [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler Shyam Sundar S K
@ 2026-05-21 10:58 ` Ilpo Järvinen
2026-05-27 10:15 ` Shyam Sundar S K
2026-05-22 13:44 ` Ilpo Järvinen
1 sibling, 1 reply; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-21 10:58 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Implement the ioctl handler for the util layer character device. This
> support adds the actual functionality to populate PMF metrics from the
> TA shared memory buffer and return them to userspace.
>
> The implementation includes:
> - amd_pmf_populate_data() to extract metrics from TA shared memory
> - amd_pmf_set_ioctl() to handle userspace ioctl requests
> - Size negotiation for forward/backward compatibility
> - Feature-based population of struct fields
>
> 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/util.c | 90 ++++++++++++++++++++++++++++-
> 1 file changed, 89 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
> index 0052f0b6a7a5..eb9a02e135a9 100644
> --- a/drivers/platform/x86/amd/pmf/util.c
> +++ b/drivers/platform/x86/amd/pmf/util.c
> @@ -19,9 +19,97 @@
> static struct amd_pmf_dev *pmf_dev_handle;
> static DEFINE_MUTEX(pmf_util_lock);
>
> +static int amd_pmf_populate_data(struct amd_pmf_dev *pdev, struct amd_pmf_info *info)
> +{
> + struct ta_pmf_shared_memory *ta_sm = NULL;
> + struct ta_pmf_enact_table *in = NULL;
> + int idx;
> +
> + if (!pdev || !info)
> + return -EINVAL;
> +
> + ta_sm = pdev->shbuf;
> + in = &ta_sm->pmf_input.enact_table;
> +
> + /* Set size and version */
> + info->size = sizeof(struct amd_pmf_info);
sizeof(*info)
version ???
> +
> + /* PMF Feature support flags */
> + if (is_apmf_func_supported(pdev, APMF_FUNC_AUTO_MODE))
> + info->features_supported |= AMD_PMF_FEAT_AUTO_MODE;
> + if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
> + info->features_supported |= AMD_PMF_FEAT_STATIC_POWER_SLIDER;
> + if (pdev->smart_pc_enabled)
> + info->features_supported |= AMD_PMF_FEAT_POLICY_BUILDER;
> + if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_AC))
> + info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC;
> + if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_DC))
> + info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC;
> +
> + /* Device States */
> + info->platform_type = in->ev_info.platform_type;
> + info->laptop_placement = in->ev_info.device_state;
> + info->lid_state = in->ev_info.lid_state;
> + info->user_presence = in->ev_info.user_present;
> + info->slider_position = in->ev_info.power_slider;
> +
> + /* Thermal and Power Metrics */
> + info->power_source = in->ev_info.power_source;
> + info->skin_temp = in->ev_info.skin_temperature;
> + info->gfx_busy = in->ev_info.gfx_busy;
> + info->ambient_light = in->ev_info.ambient_light;
> + info->avg_c0_residency = in->ev_info.avg_c0residency;
> + info->max_c0_residency = in->ev_info.max_c0residency;
> + info->socket_power = in->ev_info.socket_power;
I've no big problem with this, though I seem to now recall Hans also was
suggesting the in-kernel data would be layouted such that this copy would
be easier (but please check).
In any case, my plan is to ask Hans to check the next version of this
series now that it will be hopefully ready/almost ready.
> + /* Custom BIOS input parameters */
> + for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++) {
> + if (idx < 2)
> + info->bios_input[idx] = in->ev_info.bios_input_1[idx];
> + else
> + info->bios_input[idx] = in->ev_info.bios_input_2[idx - 2];
This seems to duplicate amd_pmf_get_ta_custom_bios_inputs().
> + }
> +
> + /* BIOS output parameters */
> + for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++)
> + info->bios_output[idx] = pdev->bios_output[idx];
> +
> + return 0;
> +}
> +
> static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> {
> - return -ENOTTY;
> + struct amd_pmf_dev *pdev = filp->private_data;
> + void __user *argp = (void __user *)arg;
> + struct amd_pmf_info info = {};
> + size_t copy_size;
> + __u64 user_size;
> + int ret;
> +
> + if (cmd != IOCTL_AMD_PMF_POPULATE_DATA)
> + return -ENOTTY;
> +
> + /* First read just the size field from userspace */
> + if (copy_from_user(&user_size, argp, sizeof(user_size)))
> + return -EFAULT;
Just an interface though, if features are ever needed as userspace ->
kernel comminucation channel, it should be handled properly right from
the start, with -EINVAL being returned for invalid (unknown) values.
This is not meant to say, you must act on this, you have better idea how
this interface may evolve over the years than I do. But if an ability to
query a set of features only would be useful at some point, it would be
beneficial to take account now as we cannot change it later to not break
ABI rules (if userspace passes struct that has only user_size initalized
and pseudogarbage in ->features, we cannot start to return -EINVAL because
of that later).
> + if (user_size & (sizeof(__u64) - 1))
Please use IS_ALIGNED() + check you have the include for it.
I wonder if user_size > sizeof(*info) is a bit dangerous condition and
should also result in -EFAULT. It result in leaving the rest of the struct
uninitialized (from userspace's PoV) when userspace and this kernel
version disagree what's the size of the struct.
> + return -EINVAL;
> +
> + guard(mutex)(&pmf_util_lock);
> + ret = amd_pmf_populate_data(pdev, &info);
> + if (ret)
> + return ret;
> +
> + copy_size = min_t(size_t, user_size, sizeof(struct amd_pmf_info));
sizeof(*info)
> +
> + /* Set actual size being copied */
> + info.size = copy_size;
> +
> + if (copy_to_user(argp, &info, copy_size))
> + return -EFAULT;
> +
> + return 0;
> }
>
> static int amd_pmf_open(struct inode *inode, struct file *filp)
>
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header
2026-05-20 18:54 ` [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header Shyam Sundar S K
@ 2026-05-21 11:02 ` Ilpo Järvinen
2026-05-27 9:37 ` Shyam Sundar S K
2026-05-22 13:35 ` Ilpo Järvinen
1 sibling, 1 reply; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-21 11:02 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> These debug helper functions convert enumerated values to appropriate
> message and can be useful for userspace tools and other kernel components
> that need to interpret AMD PMF state values.
>
> By making them inline functions in the UAPI header, they become available
> to both kernel and userspace without code duplication. Also, prefix the
> function names with amd_pmf_.
>
> 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/spc.c | 61 ++----------------------------
> include/uapi/linux/amd-pmf.h | 57 ++++++++++++++++++++++++++++
> 2 files changed, 60 insertions(+), 58 deletions(-)
> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
> index 54baf015e4c1..a8c715bee9cc 100644
> --- a/include/uapi/linux/amd-pmf.h
> +++ b/include/uapi/linux/amd-pmf.h
> @@ -115,6 +115,63 @@ enum amd_pmf_platform_type {
> AMD_PMF_PTYPE_INVALID = 0xf,
> };
>
> +/* Retrieve the platform type as a string */
> +static inline const char *amd_pmf_get_pt(unsigned int platform_type)
> +/* Retrieve the laptop placement as a string */
> +static inline const char *amd_pmf_get_lp(unsigned int device_state)
> +/* Retrieve the slider position as a string */
> +static inline const char *amd_pmf_get_sp(unsigned int state)
"pt", "lp", and "sp" are not particularly descriptive. I know they get a
bit longer if you expand them but it'd be huge win for code readability
still.
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface
2026-05-20 18:54 ` [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface Shyam Sundar S K
@ 2026-05-21 11:07 ` Ilpo Järvinen
2026-05-27 9:35 ` Shyam Sundar S K
0 siblings, 1 reply; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-21 11:07 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Add a Documentation/ABI/testing entry describing the AMD PMF util layer
> character 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.
>
> Also update the MAINTAINERS record with the new UAPI header.
>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> ---
> Documentation/ABI/testing/amdpmf-interface | 74 ++++++++++++++++++++++
> MAINTAINERS | 1 +
> 2 files changed, 75 insertions(+)
> create mode 100644 Documentation/ABI/testing/amdpmf-interface
>
> diff --git a/Documentation/ABI/testing/amdpmf-interface b/Documentation/ABI/testing/amdpmf-interface
> new file mode 100644
> index 000000000000..45606907f7e6
> --- /dev/null
> +++ b/Documentation/ABI/testing/amdpmf-interface
> @@ -0,0 +1,74 @@
> +What: /dev/amdpmf_interface
> +Date: June 2026
> +KernelVersion: 7.2
> +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 character device for feature
> + discovery and metrics monitoring.
> +
> + When CONFIG_AMD_PMF_UTIL_SUPPORT is enabled, the driver creates
> + a character device:
> +
> + ======================
> + /dev/amdpmf_interface
> + ======================
> +
> + The interface supports a single ioctl:
> +
> + ============================ =======================================
> + IOCTL Usage
> + IOCTL_AMD_PMF_POPULATE_DATA User passes a struct amd_pmf_info with
> + the size field set to sizeof(struct
> + amd_pmf_info). The driver returns all
> + available metrics and feature status
> + in the structure.
> + ============================ =======================================
> +
> + struct amd_pmf_info layout:
> +
> + ======================= ========== ================================
> + Field Type Description
> + size __u64 Structure size for versioning
> + features_version __u32 IOCTL interface version
Where does this come from?
> + features_supported __u32 Bitmask of supported features
> + platform_type __u32 Platform form factor orientation
> + power_source __u32 AC/DC power source
> + laptop_placement __u32 Device placement state
> + lid_state __u32 Lid open/closed status
> + user_presence __u32 User presence detection
> + slider_position __u32 Current power slider position
> + skin_temp __s32 Skin temperature (centidegrees)
> + gfx_busy __u32 Graphics workload percentage
> + ambient_light __s32 Ambient light sensor reading
> + avg_c0_residency __u32 Average C0 state residency
> + max_c0_residency __u32 Maximum C0 state residency
> + socket_power __u32 Socket power consumption
> + bios_input[10] __u32 Custom BIOS input parameters
> + bios_output[10] __u32 Custom BIOS output parameters
> + ======================= ========== ================================
> +
> + Feature Support Flags (features_supported bitmask):
> +
> + ===================================== ==== =============================
> + Flag Bit Description
> + AMD_PMF_FEAT_AUTO_MODE 0 Auto Mode feature support
> + AMD_PMF_FEAT_STATIC_POWER_SLIDER 1 Static Power Slider support
> + AMD_PMF_FEAT_POLICY_BUILDER 2 Policy Builder (Smart PC)
> + AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC 3 Dynamic slider on AC
> + AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC 4 Dynamic slider on DC
> + ===================================== ==== =============================
> +
> + Return codes:
> +
> + ============= ============================================================
> + Return code Description
> + 0 Success
> + EINVAL Invalid size or parameter
> + EFAULT copy_to_user/copy_from_user failures
> + ENODEV PMF device not available
> + ENOTTY Unknown ioctl command
> + ============= ============================================================
> +
> + User-space tools integrating with AMD PMF to discover capabilities and
> + monitor real-time metrics for thermal and power management validation.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 839e39825455..ec061cd127b2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1216,6 +1216,7 @@ L: platform-driver-x86@vger.kernel.org
> S: Supported
> F: Documentation/ABI/testing/sysfs-amd-pmf
> F: drivers/platform/x86/amd/pmf/
> +F: include/uapi/linux/amd-pmf.h
>
> AMD POWERPLAY AND SWSMU
> M: Kenneth Feng <kenneth.feng@amd.com>
>
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface
2026-05-20 18:54 ` [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface Shyam Sundar S K
@ 2026-05-22 13:21 ` Ilpo Järvinen
0 siblings, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-22 13:21 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Add a util layer to AMD PMF that exposes a minimal userspace interface
> via a character device for metrics monitoring and feature discovery.
>
> This creates /dev/amdpmf_interface with basic ioctl support to retrieve
> PMF metrics such as:
> * Power source and power slider position
> * Platform type, lid state, and user presence
> * Skin temperature and ambient light
> * BIOS input parameters (1-10)
> * Graphics workload metrics
> * CPU C-state residency (average and maximum)
> * Socket power consumption
>
> The interface enables smoother integration with userspace tools such as
> AMD SystemDeck [1], which is widely used for monitoring and controlling
> power and thermal behavior on AMD platforms. These tools help designers
> keep major components within thermal limits to ensure proper operation
> and enhance overall system stability and reliability.
>
> The feature is gated behind the CONFIG_AMD_PMF_UTIL_SUPPORT Kconfig
> option, allowing it to be disabled if not needed. The implementation
> uses existing PMF infrastructure to populate data from the TA (Trusted
> Application) shared memory buffer.
>
> 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 | 5 ++
> drivers/platform/x86/amd/pmf/pmf.h | 9 ++++
> drivers/platform/x86/amd/pmf/util.c | 67 +++++++++++++++++++++++++++
> include/uapi/linux/amd-pmf.h | 60 ++++++++++++++++++++++++
> 6 files changed, 153 insertions(+)
> create mode 100644 drivers/platform/x86/amd/pmf/util.c
> create mode 100644 include/uapi/linux/amd-pmf.h
>
> diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
> index 25b8f7ae3abd..ad4faf18de47 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 provides a character device for userspace to capture
> + PMF features (Smart PC Builder, Auto Mode, Static Power Slider, Dynamic
> + Power Slider AC/DC) along with PMF metrics from the AMD PMF driver.
> +
> + 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 b9e5a2cf3aae..919d02f30aae 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -634,6 +634,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
>
> pmf_device = dev->dev;
>
> + err = amd_pmf_cdev_register(dev);
> + if (err)
> + dev_warn(dev->dev, "failed to register util interface: %d\n", err);
> +
> dev_info(dev->dev, "registered PMF device successfully\n");
>
> return 0;
> @@ -646,6 +650,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();
Why is this not done in reverse order as in probe?
> apmf_acpi_deinit(dev);
> amd_pmf_dbgfs_unregister(dev);
> }
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 69fef7448744..6f61076a9386 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -928,4 +928,13 @@ int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid);
> void amd_pmf_tee_deinit(struct amd_pmf_dev *dev);
> int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev);
>
> +/* Util Layer */
> +#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
> +int amd_pmf_cdev_register(struct amd_pmf_dev *dev);
> +void amd_pmf_cdev_unregister(void);
> +#else
> +static inline int amd_pmf_cdev_register(struct amd_pmf_dev *dev) { 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..0052f0b6a7a5
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/util.c
> @@ -0,0 +1,67 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * AMD Platform Management Framework Util Layer
> + *
> + * Copyright (c) 2026, 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/amd-pmf.h>
> +#include <linux/miscdevice.h>
> +#include <linux/mutex.h>
> +#include <linux/uaccess.h>
> +
> +#include "pmf.h"
> +
> +static struct amd_pmf_dev *pmf_dev_handle;
> +static DEFINE_MUTEX(pmf_util_lock);
> +
> +static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> +{
> + return -ENOTTY;
> +}
> +
> +static int amd_pmf_open(struct inode *inode, struct file *filp)
> +{
> + guard(mutex)(&pmf_util_lock);
> + if (!pmf_dev_handle)
> + return -ENODEV;
> +
> + filp->private_data = pmf_dev_handle;
> + return 0;
> +}
> +
> +static const struct file_operations pmf_if_ops = {
> + .owner = THIS_MODULE,
> + .open = amd_pmf_open,
> + .unlocked_ioctl = amd_pmf_set_ioctl,
> +};
> +
> +static struct miscdevice amd_pmf_util_if = {
> + .minor = MISC_DYNAMIC_MINOR,
> + .name = "amdpmf_interface",
> + .fops = &pmf_if_ops,
> +};
> +
> +int amd_pmf_cdev_register(struct amd_pmf_dev *dev)
> +{
> + int ret;
> +
> + guard(mutex)(&pmf_util_lock);
> + pmf_dev_handle = dev;
> + ret = misc_register(&amd_pmf_util_if);
> + if (ret)
> + pmf_dev_handle = NULL;
> +
> + return ret;
> +}
> +
> +void amd_pmf_cdev_unregister(void)
> +{
> + guard(mutex)(&pmf_util_lock);
> + misc_deregister(&amd_pmf_util_if);
sashiko noted that if misc_register() fails, deregister is called
unconditionally.
> + pmf_dev_handle = NULL;
> +}
> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
> new file mode 100644
> index 000000000000..c7099e7f463f
> --- /dev/null
> +++ b/include/uapi/linux/amd-pmf.h
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
> +/*
> + * AMD Platform Management Framework (PMF) UAPI Header
> + *
> + * Copyright (c) 2026, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * This file defines the user-space API for interacting with the AMD PMF
> + * driver. It provides ioctl interfaces to query platform-specific metrics
> + * such as power source, slider position, platform type, laptop placement,
> + * and various BIOS input/output parameters.
> + */
> +
> +#ifndef _UAPI_LINUX_AMD_PMF_H
> +#define _UAPI_LINUX_AMD_PMF_H
> +
> +#include <linux/ioctl.h>
> +#include <linux/types.h>
> +
> +/**
> + * AMD_PMF_IOC_MAGIC - Magic number for AMD PMF ioctl commands
> + *
> + * This magic number uniquely identifies AMD PMF ioctl operations.
> + */
> +#define AMD_PMF_IOC_MAGIC 'p'
> +
> +/**
> + * IOCTL_AMD_PMF_POPULATE_DATA - ioctl command to retrieve PMF metrics data
> + *
> + * This ioctl command is used to populate the amd_pmf_info structure
> + * with the requested PMF metrics information.
> + */
> +#define IOCTL_AMD_PMF_POPULATE_DATA _IOWR(AMD_PMF_IOC_MAGIC, 0x00, struct amd_pmf_info)
> +
> +#define AMD_PMF_BIOS_PARAMS_MAX 10
> +
> +struct amd_pmf_info {
> + __u64 size;
> +
> + /* Power and state info */
> + __u32 platform_type;
> + __u32 power_source;
> + __u32 laptop_placement;
> + __u32 lid_state;
> + __u32 user_presence;
> + __u32 slider_position;
> +
> + /* Thermal and power metrics */
> + __s32 skin_temp;
> + __u32 gfx_busy;
> + __s32 ambient_light;
> + __u32 avg_c0_residency;
> + __u32 max_c0_residency;
> + __u32 socket_power;
> +
> + /* BIOS parameters */
> + __u32 bios_input[AMD_PMF_BIOS_PARAMS_MAX];
> +};
> +
> +#endif /* _UAPI_LINUX_AMD_PMF_H */
>
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 2/8] platform/x86/amd/pmf: store BIOS output values for user-space metrics via util IOCTL
2026-05-20 18:54 ` [PATCH v5 2/8] platform/x86/amd/pmf: store BIOS output values for user-space metrics via util IOCTL Shyam Sundar S K
@ 2026-05-22 13:28 ` Ilpo Järvinen
0 siblings, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-22 13:28 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Add a bios_output[] to amd_pmf_dev struct 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 metrics 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 | 2 ++
> drivers/platform/x86/amd/pmf/tee-if.c | 11 ++++++++++-
> include/uapi/linux/amd-pmf.h | 1 +
> 3 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 6f61076a9386..ffe74ebc46f8 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -130,6 +130,7 @@ struct cookie_header {
> #define GET_CMD true
>
> #define METRICS_TABLE_ID 7
> +#define BIOS_OUTPUT_MAX 10
>
> typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data);
>
> @@ -442,6 +443,7 @@ struct amd_pmf_dev {
> struct pmf_cbi_ring_buffer cbi_buf;
> struct mutex cbi_mutex; /* Protects ring buffer access */
> struct mutex metrics_mutex;
> + u32 bios_output[BIOS_OUTPUT_MAX];
> };
>
> 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 7ccd93f506b2..be8062c6691d 100644
> --- a/drivers/platform/x86/amd/pmf/tee-if.c
> +++ b/drivers/platform/x86/amd/pmf/tee-if.c
> @@ -8,7 +8,9 @@
> * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> */
>
> +#include <linux/array_size.h>
> #include <linux/debugfs.h>
> +#include <linux/dev_printk.h>
> #include <linux/tee_drv.h>
> #include <linux/uuid.h>
> #include "pmf.h"
> @@ -98,10 +100,17 @@ static int amd_pmf_get_bios_output_idx(u32 action_idx)
> static void amd_pmf_update_bios_output(struct amd_pmf_dev *pdev, struct ta_pmf_action *action)
> {
> u32 bios_idx;
> + int ret;
>
> bios_idx = amd_pmf_get_bios_output_idx(action->action_index);
> + if (bios_idx >= ARRAY_SIZE(pdev->bios_output)) {
amd_pmf_get_bios_output_idx() can return -EINVAL but it is never checked
(a pre-existing problem) and value is directly going to an unsigned type
(noted by sashiko).
> + dev_warn(pdev->dev, "BIOS output index %u out of bounds\n", bios_idx);
> + return;
> + }
>
> - amd_pmf_smartpc_apply_bios_output(pdev, action->value, BIT(bios_idx), bios_idx);
> + ret = amd_pmf_smartpc_apply_bios_output(pdev, action->value, BIT(bios_idx), bios_idx);
> + if (!ret)
> + pdev->bios_output[bios_idx] = action->value;
> }
>
> static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
> index c7099e7f463f..d29a4abe1145 100644
> --- a/include/uapi/linux/amd-pmf.h
> +++ b/include/uapi/linux/amd-pmf.h
> @@ -55,6 +55,7 @@ struct amd_pmf_info {
>
> /* BIOS parameters */
> __u32 bios_input[AMD_PMF_BIOS_PARAMS_MAX];
> + __u32 bios_output[AMD_PMF_BIOS_PARAMS_MAX];
> };
>
> #endif /* _UAPI_LINUX_AMD_PMF_H */
>
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 3/8] platform/x86/amd/pmf: Add feature discovery support to util interface
2026-05-20 18:54 ` [PATCH v5 3/8] platform/x86/amd/pmf: Add feature discovery support to util interface Shyam Sundar S K
@ 2026-05-22 13:29 ` Ilpo Järvinen
0 siblings, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-22 13:29 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Add feature discovery capability to the util layer interface, allowing
> userspace tools to query which PMF features are supported and enabled
> on the current platform.
>
> The following features can now be queried through the
> /dev/amdpmf_interface ioctl:
> * Auto Mode: Automatic power profile switching based on system activity
> * Static Power Slider: User-selectable power profiles
> * Policy Builder (Smart PC): Action based policy management
> * Dynamic Power Slider AC: Adaptive power profiles when on AC power
> * Dynamic Power Slider DC: Adaptive power profiles when on battery
>
> 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>
> ---
> include/uapi/linux/amd-pmf.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
> index d29a4abe1145..38ab5362fe62 100644
> --- a/include/uapi/linux/amd-pmf.h
> +++ b/include/uapi/linux/amd-pmf.h
> @@ -34,9 +34,19 @@
>
> #define AMD_PMF_BIOS_PARAMS_MAX 10
>
> +/* AMD PMF feature flags - bitmask indicating supported features */
> +#define AMD_PMF_FEAT_AUTO_MODE BIT(0)
> +#define AMD_PMF_FEAT_STATIC_POWER_SLIDER BIT(1)
> +#define AMD_PMF_FEAT_POLICY_BUILDER BIT(2)
> +#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC BIT(3)
> +#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC BIT(4)
Sashiko notes you lack an include for BIT().
> +
> struct amd_pmf_info {
> __u64 size;
>
> + /* Feature info */
> + __u32 features_supported;
> +
> /* Power and state info */
> __u32 platform_type;
> __u32 power_source;
>
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 4/8] platform/x86/amd/pmf: Store commonly used enums in the header file
2026-05-20 18:54 ` [PATCH v5 4/8] platform/x86/amd/pmf: Store commonly used enums in the header file Shyam Sundar S K
@ 2026-05-22 13:31 ` Ilpo Järvinen
0 siblings, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-22 13:31 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Relocate commonly used enums from multiple source files into a shared
> header file to simplify code structure, improve readability, and
> enhance maintainability. Also, remove the initialization of the first
> enum member, since it is not needed.
>
> Add the AMD_PMF_ prefix to the laptop_placement and platform_type enums
> since these names are overly generic for inclusion in a UAPI header
>
> 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>
> ---
> .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 13 ++--
> drivers/platform/x86/amd/pmf/pmf.h | 22 ------
> drivers/platform/x86/amd/pmf/spc.c | 37 +++++-----
> include/linux/amd-pmf-io.h | 9 ---
> include/uapi/linux/amd-pmf.h | 74 +++++++++++++++++++
> 5 files changed, 100 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> index 837d59e7a661..8ac44368a37d 100644
> --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
> @@ -7,6 +7,7 @@
> *
> * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
> */
> +#include <linux/amd-pmf.h>
> #include <linux/amd-pmf-io.h>
> #include <linux/io-64-nonatomic-lo-hi.h>
> #include <linux/iopoll.h>
> @@ -102,20 +103,20 @@ static int amd_sfh_mode_info(u32 *platform_type, u32 *laptop_placement)
> *platform_type = mode.op_mode.devicemode;
>
> if (mode.op_mode.ontablestate == 1) {
> - *laptop_placement = ON_TABLE;
> + *laptop_placement = AMD_PMF_ON_TABLE;
> } else if (mode.op_mode.ontablestate == 2) {
> - *laptop_placement = ON_LAP_MOTION;
> + *laptop_placement = AMD_PMF_ON_LAP_MOTION;
> } else if (mode.op_mode.inbagstate == 1) {
> - *laptop_placement = IN_BAG;
> + *laptop_placement = AMD_PMF_IN_BAG;
> } else if (mode.op_mode.outbagstate == 1) {
> - *laptop_placement = OUT_OF_BAG;
> + *laptop_placement = AMD_PMF_OUT_OF_BAG;
> } else if (mode.op_mode.ontablestate == 0 || mode.op_mode.inbagstate == 0 ||
> mode.op_mode.outbagstate == 0) {
> - *laptop_placement = LP_UNKNOWN;
> + *laptop_placement = AMD_PMF_LP_UNKNOWN;
> pr_warn_once("Unknown laptop placement\n");
> } else if (mode.op_mode.ontablestate == 3 || mode.op_mode.inbagstate == 3 ||
> mode.op_mode.outbagstate == 3) {
> - *laptop_placement = LP_UNDEFINED;
> + *laptop_placement = AMD_PMF_LP_UNDEFINED;
> pr_warn_once("Undefined laptop placement\n");
> }
>
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index ffe74ebc46f8..269c0a4b1cae 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -682,14 +682,6 @@ enum system_state {
> SYSTEM_STATE_MAX,
> };
>
> -enum ta_slider {
> - TA_BEST_BATTERY,
> - TA_BETTER_BATTERY,
> - TA_BETTER_PERFORMANCE,
> - TA_BEST_PERFORMANCE,
> - TA_MAX,
> -};
> -
> struct amd_pmf_pb_bitmap {
> const char *name;
> u32 bit_mask;
> @@ -721,20 +713,6 @@ static const struct amd_pmf_pb_bitmap custom_bios_inputs_v1[] __used = {
> {"NOTIFY_CUSTOM_BIOS_INPUT10", BIT(16)},
> };
>
> -enum platform_type {
> - PTYPE_UNKNOWN = 0,
> - LID_CLOSE,
> - CLAMSHELL,
> - FLAT,
> - TENT,
> - STAND,
> - TABLET,
> - BOOK,
> - PRESENTATION,
> - PULL_FWD,
> - PTYPE_INVALID = 0xf,
> -};
> -
> /* Command ids for TA communication */
> enum ta_pmf_command {
> TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE,
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index f48678a23cc7..05998946d1bd 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -10,6 +10,7 @@
> */
>
> #include <acpi/button.h>
> +#include <linux/amd-pmf.h>
> #include <linux/amd-pmf-io.h>
> #include <linux/cleanup.h>
> #include <linux/power_supply.h>
> @@ -20,21 +21,21 @@
> static const char *platform_type_as_str(u16 platform_type)
> {
> switch (platform_type) {
> - case CLAMSHELL:
> + case AMD_PMF_CLAMSHELL:
> return "CLAMSHELL";
> - case FLAT:
> + case AMD_PMF_FLAT:
> return "FLAT";
> - case TENT:
> + case AMD_PMF_TENT:
> return "TENT";
> - case STAND:
> + case AMD_PMF_STAND:
> return "STAND";
> - case TABLET:
> + case AMD_PMF_TABLET:
> return "TABLET";
> - case BOOK:
> + case AMD_PMF_BOOK:
> return "BOOK";
> - case PRESENTATION:
> + case AMD_PMF_PRESENTATION:
> return "PRESENTATION";
> - case PULL_FWD:
> + case AMD_PMF_PULL_FWD:
> return "PULL_FWD";
> default:
> return "UNKNOWN";
> @@ -44,13 +45,13 @@ static const char *platform_type_as_str(u16 platform_type)
> static const char *laptop_placement_as_str(u16 device_state)
> {
> switch (device_state) {
> - case ON_TABLE:
> + case AMD_PMF_ON_TABLE:
> return "ON_TABLE";
> - case ON_LAP_MOTION:
> + case AMD_PMF_ON_LAP_MOTION:
> return "ON_LAP_MOTION";
> - case IN_BAG:
> + case AMD_PMF_IN_BAG:
> return "IN_BAG";
> - case OUT_OF_BAG:
> + case AMD_PMF_OUT_OF_BAG:
> return "OUT_OF_BAG";
> default:
> return "UNKNOWN";
> @@ -60,11 +61,11 @@ static const char *laptop_placement_as_str(u16 device_state)
> static const char *ta_slider_as_str(unsigned int state)
> {
> switch (state) {
> - case TA_BEST_PERFORMANCE:
> + case AMD_PMF_TA_BEST_PERFORMANCE:
> return "PERFORMANCE";
> - case TA_BETTER_PERFORMANCE:
> + case AMD_PMF_TA_BETTER_PERFORMANCE:
> return "BALANCED";
> - case TA_BEST_BATTERY:
> + case AMD_PMF_TA_BEST_BATTERY:
> return "POWER_SAVER";
> default:
> return "Unknown TA Slider State";
> @@ -287,14 +288,14 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_
> switch (dev->current_profile) {
> case PLATFORM_PROFILE_PERFORMANCE:
> case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
> - val = TA_BEST_PERFORMANCE;
> + val = AMD_PMF_TA_BEST_PERFORMANCE;
> break;
> case PLATFORM_PROFILE_BALANCED:
> - val = TA_BETTER_PERFORMANCE;
> + val = AMD_PMF_TA_BETTER_PERFORMANCE;
> break;
> case PLATFORM_PROFILE_LOW_POWER:
> case PLATFORM_PROFILE_QUIET:
> - val = TA_BEST_BATTERY;
> + val = AMD_PMF_TA_BEST_BATTERY;
> break;
> default:
> dev_err(dev->dev, "Unknown Platform Profile.\n");
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index 55198d2875cc..e014d4ce5a20 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -52,15 +52,6 @@ struct amd_sfh_info {
> u32 laptop_placement;
> };
>
> -enum laptop_placement {
> - LP_UNKNOWN = 0,
> - ON_TABLE,
> - ON_LAP_MOTION,
> - IN_BAG,
> - OUT_OF_BAG,
> - LP_UNDEFINED,
> -};
> -
> /**
> * struct amd_pmf_npu_metrics: Get NPU metrics data from PMF driver
> * @npuclk_freq: NPU clock frequency [MHz]
> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
> index 38ab5362fe62..54baf015e4c1 100644
> --- a/include/uapi/linux/amd-pmf.h
> +++ b/include/uapi/linux/amd-pmf.h
> @@ -41,6 +41,80 @@
> #define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC BIT(3)
> #define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC BIT(4)
>
> +/**
> + * enum laptop_placement - Describes the physical placement of the laptop
Please match these with the names in the code.
> + * @AMD_PMF_LP_UNKNOWN: Placement cannot be determined
> + * @AMD_PMF_ON_TABLE: Laptop is placed on a stable surface like a table or desk
> + * @AMD_PMF_ON_LAP_MOTION: Laptop is on a lap with detected motion
> + * @AMD_PMF_IN_BAG: Laptop is detected to be inside a bag or case
> + * @AMD_PMF_OUT_OF_BAG: Laptop has been removed from bag or case
> + * @AMD_PMF_LP_UNDEFINED: Placement state is undefined
> + *
> + * This enumeration represents the physical placement state of the laptop
> + * as detected by platform sensors. Used for adaptive power management
> + * and thermal policies.
> + */
> +enum amd_pmf_laptop_placement {
> + AMD_PMF_LP_UNKNOWN,
> + AMD_PMF_ON_TABLE,
> + AMD_PMF_ON_LAP_MOTION,
> + AMD_PMF_IN_BAG,
> + AMD_PMF_OUT_OF_BAG,
> + AMD_PMF_LP_UNDEFINED,
> +};
> +
> +/**
> + * enum ta_slider - Trusted Application power slider positions
> + * @AMD_PMF_TA_BEST_BATTERY: Maximum battery savings, minimal performance
> + * @AMD_PMF_TA_BETTER_BATTERY: Balanced towards battery life
> + * @AMD_PMF_TA_BETTER_PERFORMANCE: Balanced towards performance
> + * @AMD_PMF_TA_BEST_PERFORMANCE: Maximum performance, higher power consumption
> + * @AMD_PMF_TA_MAX: Sentinel value indicating maximum enum value
> + *
> + * This enumeration defines the power slider positions used by the
> + * AMD PMF Trusted Application for dynamic power management decisions.
> + * These correspond to the Windows power slider UI positions.
> + */
> +enum amd_pmf_ta_slider {
> + AMD_PMF_TA_BEST_BATTERY,
> + AMD_PMF_TA_BETTER_BATTERY,
> + AMD_PMF_TA_BETTER_PERFORMANCE,
> + AMD_PMF_TA_BEST_PERFORMANCE,
> + AMD_PMF_TA_MAX,
> +};
> +
> +/**
> + * enum platform_type - Describes the physical form factor orientation
> + * @AMD_PMF_PTYPE_UNKNOWN: Platform type cannot be determined
> + * @AMD_PMF_LID_CLOSE: Laptop lid is closed
> + * @AMD_PMF_CLAMSHELL: Traditional laptop mode with keyboard and screen
> + * @AMD_PMF_FLAT: Device is lying flat on a surface
> + * @AMD_PMF_TENT: Device is in tent mode (keyboard folded back, standing)
> + * @AMD_PMF_STAND: Device is propped up in stand orientation
> + * @AMD_PMF_TABLET: Device is in tablet mode with keyboard hidden
> + * @AMD_PMF_BOOK: Device is in book reading orientation
> + * @AMD_PMF_PRESENTATION: Device is in presentation mode
> + * @AMD_PMF_PULL_FWD: Screen is pulled forward towards user
> + * @AMD_PMF_PTYPE_INVALID: Invalid platform type marker
> + *
> + * This enumeration describes the current physical orientation or form
> + * factor of convertible/2-in-1 devices. Used for optimizing power and
> + * thermal management based on device posture.
> + */
> +enum amd_pmf_platform_type {
> + AMD_PMF_PTYPE_UNKNOWN,
> + AMD_PMF_LID_CLOSE,
> + AMD_PMF_CLAMSHELL,
> + AMD_PMF_FLAT,
> + AMD_PMF_TENT,
> + AMD_PMF_STAND,
> + AMD_PMF_TABLET,
> + AMD_PMF_BOOK,
> + AMD_PMF_PRESENTATION,
> + AMD_PMF_PULL_FWD,
> + AMD_PMF_PTYPE_INVALID = 0xf,
> +};
> +
> struct amd_pmf_info {
> __u64 size;
>
>
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header
2026-05-20 18:54 ` [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header Shyam Sundar S K
2026-05-21 11:02 ` Ilpo Järvinen
@ 2026-05-22 13:35 ` Ilpo Järvinen
1 sibling, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-22 13:35 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> These debug helper functions convert enumerated values to appropriate
> message and can be useful for userspace tools and other kernel components
> that need to interpret AMD PMF state values.
>
> By making them inline functions in the UAPI header, they become available
> to both kernel and userspace without code duplication. Also, prefix the
> function names with amd_pmf_.
>
> 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/spc.c | 61 ++----------------------------
> include/uapi/linux/amd-pmf.h | 57 ++++++++++++++++++++++++++++
> 2 files changed, 60 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
> index 05998946d1bd..0606d3b0adde 100644
> --- a/drivers/platform/x86/amd/pmf/spc.c
> +++ b/drivers/platform/x86/amd/pmf/spc.c
> @@ -18,60 +18,6 @@
> #include "pmf.h"
>
> #ifdef CONFIG_AMD_PMF_DEBUG
> -static const char *platform_type_as_str(u16 platform_type)
> -{
> - switch (platform_type) {
> - case AMD_PMF_CLAMSHELL:
> - return "CLAMSHELL";
> - case AMD_PMF_FLAT:
> - return "FLAT";
> - case AMD_PMF_TENT:
> - return "TENT";
> - case AMD_PMF_STAND:
> - return "STAND";
> - case AMD_PMF_TABLET:
> - return "TABLET";
> - case AMD_PMF_BOOK:
> - return "BOOK";
> - case AMD_PMF_PRESENTATION:
> - return "PRESENTATION";
> - case AMD_PMF_PULL_FWD:
> - return "PULL_FWD";
> - default:
> - return "UNKNOWN";
> - }
> -}
> -
> -static const char *laptop_placement_as_str(u16 device_state)
> -{
> - switch (device_state) {
> - case AMD_PMF_ON_TABLE:
> - return "ON_TABLE";
> - case AMD_PMF_ON_LAP_MOTION:
> - return "ON_LAP_MOTION";
> - case AMD_PMF_IN_BAG:
> - return "IN_BAG";
> - case AMD_PMF_OUT_OF_BAG:
> - return "OUT_OF_BAG";
> - default:
> - return "UNKNOWN";
> - }
> -}
> -
> -static const char *ta_slider_as_str(unsigned int state)
> -{
> - switch (state) {
> - case AMD_PMF_TA_BEST_PERFORMANCE:
> - return "PERFORMANCE";
> - case AMD_PMF_TA_BETTER_PERFORMANCE:
> - return "BALANCED";
> - case AMD_PMF_TA_BEST_BATTERY:
> - return "POWER_SAVER";
> - default:
> - return "Unknown TA Slider State";
> - }
> -}
> -
> static u32 amd_pmf_get_ta_custom_bios_inputs(struct ta_pmf_enact_table *in, int index)
> {
> switch (index) {
> @@ -89,7 +35,7 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
> int i;
>
> dev_dbg(dev->dev, "==== TA inputs START ====\n");
> - dev_dbg(dev->dev, "Slider State: %s\n", ta_slider_as_str(in->ev_info.power_slider));
> + dev_dbg(dev->dev, "Slider State: %s\n", amd_pmf_get_sp(in->ev_info.power_slider));
> dev_dbg(dev->dev, "Power Source: %s\n", amd_pmf_source_as_str(in->ev_info.power_source));
> dev_dbg(dev->dev, "Battery Percentage: %u\n", in->ev_info.bat_percentage);
> dev_dbg(dev->dev, "Designed Battery Capacity: %u\n", in->ev_info.bat_design);
> @@ -103,9 +49,8 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
> dev_dbg(dev->dev, "LID State: %s\n", in->ev_info.lid_state ? "close" : "open");
> dev_dbg(dev->dev, "User Presence: %s\n", in->ev_info.user_present ? "Present" : "Away");
> dev_dbg(dev->dev, "Ambient Light: %d\n", in->ev_info.ambient_light);
> - dev_dbg(dev->dev, "Platform type: %s\n", platform_type_as_str(in->ev_info.platform_type));
> - dev_dbg(dev->dev, "Laptop placement: %s\n",
> - laptop_placement_as_str(in->ev_info.device_state));
> + dev_dbg(dev->dev, "Platform type: %s\n", amd_pmf_get_pt(in->ev_info.platform_type));
> + dev_dbg(dev->dev, "Laptop placement: %s\n", amd_pmf_get_lp(in->ev_info.device_state));
> for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
> dev_dbg(dev->dev, "Custom BIOS input%d: %u\n", i + 1,
> amd_pmf_get_ta_custom_bios_inputs(in, i));
> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
> index 54baf015e4c1..a8c715bee9cc 100644
> --- a/include/uapi/linux/amd-pmf.h
> +++ b/include/uapi/linux/amd-pmf.h
> @@ -115,6 +115,63 @@ enum amd_pmf_platform_type {
> AMD_PMF_PTYPE_INVALID = 0xf,
> };
>
> +/* Retrieve the platform type as a string */
> +static inline const char *amd_pmf_get_pt(unsigned int platform_type)
> +{
> + switch (platform_type) {
> + case AMD_PMF_CLAMSHELL:
> + return "CLAMSHELL";
> + case AMD_PMF_FLAT:
> + return "FLAT";
> + case AMD_PMF_TENT:
> + return "TENT";
> + case AMD_PMF_STAND:
> + return "STAND";
> + case AMD_PMF_TABLET:
> + return "TABLET";
> + case AMD_PMF_BOOK:
> + return "BOOK";
> + case AMD_PMF_PRESENTATION:
> + return "PRESENTATION";
> + case AMD_PMF_PULL_FWD:
> + return "PULL_FWD";
> + default:
> + return "UNKNOWN";
> + }
> +}
> +
> +/* Retrieve the laptop placement as a string */
> +static inline const char *amd_pmf_get_lp(unsigned int device_state)
> +{
> + switch (device_state) {
> + case AMD_PMF_ON_TABLE:
> + return "ON_TABLE";
> + case AMD_PMF_ON_LAP_MOTION:
> + return "ON_LAP_MOTION";
> + case AMD_PMF_IN_BAG:
> + return "IN_BAG";
> + case AMD_PMF_OUT_OF_BAG:
> + return "OUT_OF_BAG";
> + default:
> + return "UNKNOWN";
> + }
> +}
> +
> +/* Retrieve the slider position as a string */
> +static inline const char *amd_pmf_get_sp(unsigned int state)
> +{
> + switch (state) {
> + case AMD_PMF_TA_BEST_PERFORMANCE:
> + return "PERFORMANCE";
> + case AMD_PMF_TA_BETTER_PERFORMANCE:
> + return "BALANCED";
> + case AMD_PMF_TA_BEST_BATTERY:
> + return "POWER_SAVER";
> + default:
> + return "Unknown TA Slider State";
> + }
> +}
> +
> struct amd_pmf_info {
> __u64 size;
>
>
Sashiko complains about missing a few enum values, please check if those
should be covered. And if not, missing things should be justified in the
changelog so nobody ends up wondering "why?" later on.
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler
2026-05-20 18:54 ` [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler Shyam Sundar S K
2026-05-21 10:58 ` Ilpo Järvinen
@ 2026-05-22 13:44 ` Ilpo Järvinen
1 sibling, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-22 13:44 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On Thu, 21 May 2026, Shyam Sundar S K wrote:
> Implement the ioctl handler for the util layer character device. This
> support adds the actual functionality to populate PMF metrics from the
> TA shared memory buffer and return them to userspace.
>
> The implementation includes:
> - amd_pmf_populate_data() to extract metrics from TA shared memory
> - amd_pmf_set_ioctl() to handle userspace ioctl requests
> - Size negotiation for forward/backward compatibility
> - Feature-based population of struct fields
>
> 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/util.c | 90 ++++++++++++++++++++++++++++-
> 1 file changed, 89 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
> index 0052f0b6a7a5..eb9a02e135a9 100644
> --- a/drivers/platform/x86/amd/pmf/util.c
> +++ b/drivers/platform/x86/amd/pmf/util.c
> @@ -19,9 +19,97 @@
> static struct amd_pmf_dev *pmf_dev_handle;
> static DEFINE_MUTEX(pmf_util_lock);
>
> +static int amd_pmf_populate_data(struct amd_pmf_dev *pdev, struct amd_pmf_info *info)
> +{
> + struct ta_pmf_shared_memory *ta_sm = NULL;
> + struct ta_pmf_enact_table *in = NULL;
> + int idx;
> +
> + if (!pdev || !info)
> + return -EINVAL;
> +
> + ta_sm = pdev->shbuf;
> + in = &ta_sm->pmf_input.enact_table;
Please check sashiko's report on unconditionally dereferencing shbuf (vs
smart pc not supported).
There may be validity in many of the other issues sashiko notes as well,
you can look the rest yourself (but please don't think it would always
be right).
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface
2026-05-21 11:07 ` Ilpo Järvinen
@ 2026-05-27 9:35 ` Shyam Sundar S K
0 siblings, 0 replies; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-27 9:35 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On 5/21/2026 16:37, Ilpo Järvinen wrote:
> On Thu, 21 May 2026, Shyam Sundar S K wrote:
>
>> Add a Documentation/ABI/testing entry describing the AMD PMF util layer
>> character 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.
>>
>> Also update the MAINTAINERS record with the new UAPI header.
>>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> ---
>> Documentation/ABI/testing/amdpmf-interface | 74 ++++++++++++++++++++++
>> MAINTAINERS | 1 +
>> 2 files changed, 75 insertions(+)
>> create mode 100644 Documentation/ABI/testing/amdpmf-interface
>>
>> diff --git a/Documentation/ABI/testing/amdpmf-interface b/Documentation/ABI/testing/amdpmf-interface
>> new file mode 100644
>> index 000000000000..45606907f7e6
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/amdpmf-interface
>> @@ -0,0 +1,74 @@
>> +What: /dev/amdpmf_interface
>> +Date: June 2026
>> +KernelVersion: 7.2
>> +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 character device for feature
>> + discovery and metrics monitoring.
>> +
>> + When CONFIG_AMD_PMF_UTIL_SUPPORT is enabled, the driver creates
>> + a character device:
>> +
>> + ======================
>> + /dev/amdpmf_interface
>> + ======================
>> +
>> + The interface supports a single ioctl:
>> +
>> + ============================ =======================================
>> + IOCTL Usage
>> + IOCTL_AMD_PMF_POPULATE_DATA User passes a struct amd_pmf_info with
>> + the size field set to sizeof(struct
>> + amd_pmf_info). The driver returns all
>> + available metrics and feature status
>> + in the structure.
>> + ============================ =======================================
>> +
>> + struct amd_pmf_info layout:
>> +
>> + ======================= ========== ================================
>> + Field Type Description
>> + size __u64 Structure size for versioning
>> + features_version __u32 IOCTL interface version
>
> Where does this come from?
Nice catch! Will update in v6.
Thanks,
Shyam
>
>> + features_supported __u32 Bitmask of supported features
>> + platform_type __u32 Platform form factor orientation
>> + power_source __u32 AC/DC power source
>> + laptop_placement __u32 Device placement state
>> + lid_state __u32 Lid open/closed status
>> + user_presence __u32 User presence detection
>> + slider_position __u32 Current power slider position
>> + skin_temp __s32 Skin temperature (centidegrees)
>> + gfx_busy __u32 Graphics workload percentage
>> + ambient_light __s32 Ambient light sensor reading
>> + avg_c0_residency __u32 Average C0 state residency
>> + max_c0_residency __u32 Maximum C0 state residency
>> + socket_power __u32 Socket power consumption
>> + bios_input[10] __u32 Custom BIOS input parameters
>> + bios_output[10] __u32 Custom BIOS output parameters
>> + ======================= ========== ================================
>> +
>> + Feature Support Flags (features_supported bitmask):
>> +
>> + ===================================== ==== =============================
>> + Flag Bit Description
>> + AMD_PMF_FEAT_AUTO_MODE 0 Auto Mode feature support
>> + AMD_PMF_FEAT_STATIC_POWER_SLIDER 1 Static Power Slider support
>> + AMD_PMF_FEAT_POLICY_BUILDER 2 Policy Builder (Smart PC)
>> + AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC 3 Dynamic slider on AC
>> + AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC 4 Dynamic slider on DC
>> + ===================================== ==== =============================
>> +
>> + Return codes:
>> +
>> + ============= ============================================================
>> + Return code Description
>> + 0 Success
>> + EINVAL Invalid size or parameter
>> + EFAULT copy_to_user/copy_from_user failures
>> + ENODEV PMF device not available
>> + ENOTTY Unknown ioctl command
>> + ============= ============================================================
>> +
>> + User-space tools integrating with AMD PMF to discover capabilities and
>> + monitor real-time metrics for thermal and power management validation.
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 839e39825455..ec061cd127b2 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1216,6 +1216,7 @@ L: platform-driver-x86@vger.kernel.org
>> S: Supported
>> F: Documentation/ABI/testing/sysfs-amd-pmf
>> F: drivers/platform/x86/amd/pmf/
>> +F: include/uapi/linux/amd-pmf.h
>>
>> AMD POWERPLAY AND SWSMU
>> M: Kenneth Feng <kenneth.feng@amd.com>
>>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header
2026-05-21 11:02 ` Ilpo Järvinen
@ 2026-05-27 9:37 ` Shyam Sundar S K
0 siblings, 0 replies; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-27 9:37 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On 5/21/2026 16:32, Ilpo Järvinen wrote:
> On Thu, 21 May 2026, Shyam Sundar S K wrote:
>
>> These debug helper functions convert enumerated values to appropriate
>> message and can be useful for userspace tools and other kernel components
>> that need to interpret AMD PMF state values.
>>
>> By making them inline functions in the UAPI header, they become available
>> to both kernel and userspace without code duplication. Also, prefix the
>> function names with amd_pmf_.
>>
>> 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/spc.c | 61 ++----------------------------
>> include/uapi/linux/amd-pmf.h | 57 ++++++++++++++++++++++++++++
>> 2 files changed, 60 insertions(+), 58 deletions(-)
>
>
>> diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h
>> index 54baf015e4c1..a8c715bee9cc 100644
>> --- a/include/uapi/linux/amd-pmf.h
>> +++ b/include/uapi/linux/amd-pmf.h
>> @@ -115,6 +115,63 @@ enum amd_pmf_platform_type {
>> AMD_PMF_PTYPE_INVALID = 0xf,
>> };
>>
>> +/* Retrieve the platform type as a string */
>> +static inline const char *amd_pmf_get_pt(unsigned int platform_type)
>
>> +/* Retrieve the laptop placement as a string */
>> +static inline const char *amd_pmf_get_lp(unsigned int device_state)
>
>> +/* Retrieve the slider position as a string */
>> +static inline const char *amd_pmf_get_sp(unsigned int state)
>
> "pt", "lp", and "sp" are not particularly descriptive. I know they get a
> bit longer if you expand them but it'd be huge win for code readability
> still.
>
Ack to all the comments for patches from 1 to 5. Specific to this
feedback, I thought instead of having long names thought to shorten it
as "pt", "lp" etc along with a comment to say what that function does.
But, yeah; I get your point. Shall change it to longer names in v6.
Thanks,
Shyam
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler
2026-05-21 10:58 ` Ilpo Järvinen
@ 2026-05-27 10:15 ` Shyam Sundar S K
2026-05-27 11:09 ` Ilpo Järvinen
0 siblings, 1 reply; 22+ messages in thread
From: Shyam Sundar S K @ 2026-05-27 10:15 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
On 5/21/2026 16:28, Ilpo Järvinen wrote:
> On Thu, 21 May 2026, Shyam Sundar S K wrote:
>
>> Implement the ioctl handler for the util layer character device. This
>> support adds the actual functionality to populate PMF metrics from the
>> TA shared memory buffer and return them to userspace.
>>
>> The implementation includes:
>> - amd_pmf_populate_data() to extract metrics from TA shared memory
>> - amd_pmf_set_ioctl() to handle userspace ioctl requests
>> - Size negotiation for forward/backward compatibility
>> - Feature-based population of struct fields
>>
>> 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/util.c | 90 ++++++++++++++++++++++++++++-
>> 1 file changed, 89 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
>> index 0052f0b6a7a5..eb9a02e135a9 100644
>> --- a/drivers/platform/x86/amd/pmf/util.c
>> +++ b/drivers/platform/x86/amd/pmf/util.c
>> @@ -19,9 +19,97 @@
>> static struct amd_pmf_dev *pmf_dev_handle;
>> static DEFINE_MUTEX(pmf_util_lock);
>>
>> +static int amd_pmf_populate_data(struct amd_pmf_dev *pdev, struct amd_pmf_info *info)
>> +{
>> + struct ta_pmf_shared_memory *ta_sm = NULL;
>> + struct ta_pmf_enact_table *in = NULL;
>> + int idx;
>> +
>> + if (!pdev || !info)
>> + return -EINVAL;
>> +
>> + ta_sm = pdev->shbuf;
>> + in = &ta_sm->pmf_input.enact_table;
>> +
>> + /* Set size and version */
>> + info->size = sizeof(struct amd_pmf_info);
>
> sizeof(*info)
>
> version ???
>
>> +
>> + /* PMF Feature support flags */
>> + if (is_apmf_func_supported(pdev, APMF_FUNC_AUTO_MODE))
>> + info->features_supported |= AMD_PMF_FEAT_AUTO_MODE;
>> + if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
>> + info->features_supported |= AMD_PMF_FEAT_STATIC_POWER_SLIDER;
>> + if (pdev->smart_pc_enabled)
>> + info->features_supported |= AMD_PMF_FEAT_POLICY_BUILDER;
>> + if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_AC))
>> + info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC;
>> + if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_DC))
>> + info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC;
>> +
>> + /* Device States */
>> + info->platform_type = in->ev_info.platform_type;
>> + info->laptop_placement = in->ev_info.device_state;
>> + info->lid_state = in->ev_info.lid_state;
>> + info->user_presence = in->ev_info.user_present;
>> + info->slider_position = in->ev_info.power_slider;
>> +
>> + /* Thermal and Power Metrics */
>> + info->power_source = in->ev_info.power_source;
>> + info->skin_temp = in->ev_info.skin_temperature;
>> + info->gfx_busy = in->ev_info.gfx_busy;
>> + info->ambient_light = in->ev_info.ambient_light;
>> + info->avg_c0_residency = in->ev_info.avg_c0residency;
>> + info->max_c0_residency = in->ev_info.max_c0residency;
>> + info->socket_power = in->ev_info.socket_power;
>
> I've no big problem with this, though I seem to now recall Hans also was
> suggesting the in-kernel data would be layouted such that this copy would
> be easier (but please check).
>
> In any case, my plan is to ask Hans to check the next version of this
> series now that it will be hopefully ready/almost ready.
Sure. We can gather feedback from Hans once you are comfortable with
the changes in v6.
>
>> + /* Custom BIOS input parameters */
>> + for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++) {
>> + if (idx < 2)
>> + info->bios_input[idx] = in->ev_info.bios_input_1[idx];
>> + else
>> + info->bios_input[idx] = in->ev_info.bios_input_2[idx - 2];
>
> This seems to duplicate amd_pmf_get_ta_custom_bios_inputs().
Not sure how they are duplicates..
amd_pmf_get_ta_custom_bios_inputs() -> just returns the index of the
bios input
But, here in this code snippet, we store the values of the bios inputs
to propagate back to the userland.
>
>> + }
>> +
>> + /* BIOS output parameters */
>> + for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++)
>> + info->bios_output[idx] = pdev->bios_output[idx];
>> +
>> + return 0;
>> +}
>> +
>> static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>> {
>> - return -ENOTTY;
>> + struct amd_pmf_dev *pdev = filp->private_data;
>> + void __user *argp = (void __user *)arg;
>> + struct amd_pmf_info info = {};
>> + size_t copy_size;
>> + __u64 user_size;
>> + int ret;
>> +
>> + if (cmd != IOCTL_AMD_PMF_POPULATE_DATA)
>> + return -ENOTTY;
>> +
>> + /* First read just the size field from userspace */
>> + if (copy_from_user(&user_size, argp, sizeof(user_size)))
>> + return -EFAULT;
>
> Just an interface though, if features are ever needed as userspace ->
> kernel comminucation channel, it should be handled properly right from
> the start, with -EINVAL being returned for invalid (unknown) values.
>
> This is not meant to say, you must act on this, you have better idea how
> this interface may evolve over the years than I do. But if an ability to
> query a set of features only would be useful at some point, it would be
> beneficial to take account now as we cannot change it later to not break
> ABI rules (if userspace passes struct that has only user_size initalized
> and pseudogarbage in ->features, we cannot start to return -EINVAL because
> of that later).
The thought process was to have an interface where the userspace can
query what features are/were supported and as unidirectional
communication channel.
But, we never know what might actually come up in future. So, would
like to address your comment now.
Can you please check if this is what you are expecting?
if (user_size > sizeof(__u64)) {
__u32 features_from_user = 0;
if (copy_from_user(&features_from_user, argp + offsetof(struct
amd_pmf_info, features_supported),
sizeof(features_from_user)))
return -EFAULT;
// Reject non-zero values NOW
if (features_from_user != 0)
return -EINVAL; // ← Forces userspace to zero-initialize!
}
Kindly let me know if you think otherwise.
>
>> + if (user_size & (sizeof(__u64) - 1))
>
> Please use IS_ALIGNED() + check you have the include for it.
Ack.
>
> I wonder if user_size > sizeof(*info) is a bit dangerous condition and
> should also result in -EFAULT. It result in leaving the rest of the struct
> uninitialized (from userspace's PoV) when userspace and this kernel
> version disagree what's the size of the struct.
>
So,
+ if (!IS_ALIGNED(user_size, sizeof(__u64)))
+ return -EINVAL;
Should help address your comment right?
If no, I think I am missing your feedback. Can you elaborate?
>> + return -EINVAL;
>> +
>> + guard(mutex)(&pmf_util_lock);
>> + ret = amd_pmf_populate_data(pdev, &info);
>> + if (ret)
>> + return ret;
>> +
>> + copy_size = min_t(size_t, user_size, sizeof(struct amd_pmf_info));
>
> sizeof(*info)
Ack.
Thanks,
Shyam
>
>> +
>> + /* Set actual size being copied */
>> + info.size = copy_size;
>> +
>> + if (copy_to_user(argp, &info, copy_size))
>> + return -EFAULT;
>> +
>> + return 0;
>> }
>>
>> static int amd_pmf_open(struct inode *inode, struct file *filp)
>>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler
2026-05-27 10:15 ` Shyam Sundar S K
@ 2026-05-27 11:09 ` Ilpo Järvinen
0 siblings, 0 replies; 22+ messages in thread
From: Ilpo Järvinen @ 2026-05-27 11:09 UTC (permalink / raw)
To: Shyam Sundar S K
Cc: Hans de Goede, platform-driver-x86, mario.limonciello,
Sanket.Goswami
[-- Attachment #1: Type: text/plain, Size: 8291 bytes --]
On Wed, 27 May 2026, Shyam Sundar S K wrote:
> On 5/21/2026 16:28, Ilpo Järvinen wrote:
> > On Thu, 21 May 2026, Shyam Sundar S K wrote:
> >
> >> Implement the ioctl handler for the util layer character device. This
> >> support adds the actual functionality to populate PMF metrics from the
> >> TA shared memory buffer and return them to userspace.
> >>
> >> The implementation includes:
> >> - amd_pmf_populate_data() to extract metrics from TA shared memory
> >> - amd_pmf_set_ioctl() to handle userspace ioctl requests
> >> - Size negotiation for forward/backward compatibility
> >> - Feature-based population of struct fields
> >>
> >> 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/util.c | 90 ++++++++++++++++++++++++++++-
> >> 1 file changed, 89 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c
> >> index 0052f0b6a7a5..eb9a02e135a9 100644
> >> --- a/drivers/platform/x86/amd/pmf/util.c
> >> +++ b/drivers/platform/x86/amd/pmf/util.c
> >> @@ -19,9 +19,97 @@
> >> static struct amd_pmf_dev *pmf_dev_handle;
> >> static DEFINE_MUTEX(pmf_util_lock);
> >>
> >> +static int amd_pmf_populate_data(struct amd_pmf_dev *pdev, struct amd_pmf_info *info)
> >> +{
> >> + struct ta_pmf_shared_memory *ta_sm = NULL;
> >> + struct ta_pmf_enact_table *in = NULL;
> >> + int idx;
> >> +
> >> + if (!pdev || !info)
> >> + return -EINVAL;
> >> +
> >> + ta_sm = pdev->shbuf;
> >> + in = &ta_sm->pmf_input.enact_table;
> >> +
> >> + /* Set size and version */
> >> + info->size = sizeof(struct amd_pmf_info);
> >
> > sizeof(*info)
> >
> > version ???
> >
> >> +
> >> + /* PMF Feature support flags */
> >> + if (is_apmf_func_supported(pdev, APMF_FUNC_AUTO_MODE))
> >> + info->features_supported |= AMD_PMF_FEAT_AUTO_MODE;
> >> + if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
> >> + info->features_supported |= AMD_PMF_FEAT_STATIC_POWER_SLIDER;
> >> + if (pdev->smart_pc_enabled)
> >> + info->features_supported |= AMD_PMF_FEAT_POLICY_BUILDER;
> >> + if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_AC))
> >> + info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC;
> >> + if (is_apmf_func_supported(pdev, APMF_FUNC_DYN_SLIDER_DC))
> >> + info->features_supported |= AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC;
> >> +
> >> + /* Device States */
> >> + info->platform_type = in->ev_info.platform_type;
> >> + info->laptop_placement = in->ev_info.device_state;
> >> + info->lid_state = in->ev_info.lid_state;
> >> + info->user_presence = in->ev_info.user_present;
> >> + info->slider_position = in->ev_info.power_slider;
> >> +
> >> + /* Thermal and Power Metrics */
> >> + info->power_source = in->ev_info.power_source;
> >> + info->skin_temp = in->ev_info.skin_temperature;
> >> + info->gfx_busy = in->ev_info.gfx_busy;
> >> + info->ambient_light = in->ev_info.ambient_light;
> >> + info->avg_c0_residency = in->ev_info.avg_c0residency;
> >> + info->max_c0_residency = in->ev_info.max_c0residency;
> >> + info->socket_power = in->ev_info.socket_power;
> >
> > I've no big problem with this, though I seem to now recall Hans also was
> > suggesting the in-kernel data would be layouted such that this copy would
> > be easier (but please check).
> >
> > In any case, my plan is to ask Hans to check the next version of this
> > series now that it will be hopefully ready/almost ready.
>
> Sure. We can gather feedback from Hans once you are comfortable with
> the changes in v6.
>
> >
> >> + /* Custom BIOS input parameters */
> >> + for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++) {
> >> + if (idx < 2)
> >> + info->bios_input[idx] = in->ev_info.bios_input_1[idx];
> >> + else
> >> + info->bios_input[idx] = in->ev_info.bios_input_2[idx - 2];
> >
> > This seems to duplicate amd_pmf_get_ta_custom_bios_inputs().
>
> Not sure how they are duplicates..
>
> amd_pmf_get_ta_custom_bios_inputs() -> just returns the index of the
> bios input
>
> But, here in this code snippet, we store the values of the bios inputs
> to propagate back to the userland.
Isn't the loop equivalent to this:
for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++) {
info->bios_input[idx] = amd_pmf_get_ta_custom_bios_inputs(id, idx);
> >> + }
> >> +
> >> + /* BIOS output parameters */
> >> + for (idx = 0; idx < AMD_PMF_BIOS_PARAMS_MAX; idx++)
> >> + info->bios_output[idx] = pdev->bios_output[idx];
> >> +
> >> + return 0;
> >> +}
> >> +
> >> static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> >> {
> >> - return -ENOTTY;
> >> + struct amd_pmf_dev *pdev = filp->private_data;
> >> + void __user *argp = (void __user *)arg;
> >> + struct amd_pmf_info info = {};
> >> + size_t copy_size;
> >> + __u64 user_size;
> >> + int ret;
> >> +
> >> + if (cmd != IOCTL_AMD_PMF_POPULATE_DATA)
> >> + return -ENOTTY;
> >> +
> >> + /* First read just the size field from userspace */
> >> + if (copy_from_user(&user_size, argp, sizeof(user_size)))
> >> + return -EFAULT;
> >
> > Just an interface though, if features are ever needed as userspace ->
> > kernel comminucation channel, it should be handled properly right from
> > the start, with -EINVAL being returned for invalid (unknown) values.
> >
> > This is not meant to say, you must act on this, you have better idea how
> > this interface may evolve over the years than I do. But if an ability to
> > query a set of features only would be useful at some point, it would be
> > beneficial to take account now as we cannot change it later to not break
> > ABI rules (if userspace passes struct that has only user_size initalized
> > and pseudogarbage in ->features, we cannot start to return -EINVAL because
> > of that later).
>
> The thought process was to have an interface where the userspace can
> query what features are/were supported and as unidirectional
> communication channel.
It's already bidirectional because of size.
> But, we never know what might actually come up in future. So, would
> like to address your comment now.
>
> Can you please check if this is what you are expecting?
>
> if (user_size > sizeof(__u64)) {
> __u32 features_from_user = 0;
>
> if (copy_from_user(&features_from_user, argp + offsetof(struct
> amd_pmf_info, features_supported),
> sizeof(features_from_user)))
> return -EFAULT;
>
> // Reject non-zero values NOW
> if (features_from_user != 0)
> return -EINVAL; // ← Forces userspace to zero-initialize!
Yes, this is is the check I was interesting in seeing.
> }
I suggest you first copy both size and features fields.
> > I wonder if user_size > sizeof(*info) is a bit dangerous condition and
> > should also result in -EFAULT. It result in leaving the rest of the struct
> > uninitialized (from userspace's PoV) when userspace and this kernel
> > version disagree what's the size of the struct.
> >
>
> So,
>
> + if (!IS_ALIGNED(user_size, sizeof(__u64)))
> + return -EINVAL;
>
> Should help address your comment right?
>
> If no, I think I am missing your feedback. Can you elaborate?
No, it doesn't.
Kernel copies only sizeof(*info) worth of bytes back to userspace, if
userspace asks more than sizeof(*info), the rest is left as it was (not
zeroed). Arguably, info.size tells userspace how much was actually copied
but in practice this happens when userspace has struct amd_pmf_info which
is different from that of kernel's (userspace tool was built with newer
kernel headers than it now executes on). Accepting such partially filled
struct in userspace will be walking on a cliff edge because some of the
fields will not be filled with values but garbage.
Maybe this is userspace's own problem. I'm just trying to think various
pitfalls the interface could have. And if userspace does properly
initialize the struct before calling kernel, it doesn't have so big
problem.
--
i.
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2026-05-27 11:09 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-20 18:54 [PATCH v5 0/8] platform/x86/amd/pmf: Introduce PMF util layer with userspace interface Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 1/8] platform/x86/amd/pmf: Add util layer and userspace character device interface Shyam Sundar S K
2026-05-22 13:21 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 2/8] platform/x86/amd/pmf: store BIOS output values for user-space metrics via util IOCTL Shyam Sundar S K
2026-05-22 13:28 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 3/8] platform/x86/amd/pmf: Add feature discovery support to util interface Shyam Sundar S K
2026-05-22 13:29 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 4/8] platform/x86/amd/pmf: Store commonly used enums in the header file Shyam Sundar S K
2026-05-22 13:31 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 5/8] platform/x86/amd/pmf: Move debug helper functions to UAPI header Shyam Sundar S K
2026-05-21 11:02 ` Ilpo Järvinen
2026-05-27 9:37 ` Shyam Sundar S K
2026-05-22 13:35 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 6/8] platform/x86/amd/pmf: Implement util layer ioctl handler Shyam Sundar S K
2026-05-21 10:58 ` Ilpo Järvinen
2026-05-27 10:15 ` Shyam Sundar S K
2026-05-27 11:09 ` Ilpo Järvinen
2026-05-22 13:44 ` Ilpo Järvinen
2026-05-20 18:54 ` [PATCH v5 7/8] platform/x86/amd/pmf: Introduce AMD PMF testing tool for driver metrics and features Shyam Sundar S K
2026-05-20 18:54 ` [PATCH v5 8/8] Documentation/ABI: add testing entry for AMD PMF character device interface Shyam Sundar S K
2026-05-21 11:07 ` Ilpo Järvinen
2026-05-27 9:35 ` Shyam Sundar S K
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.