mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-21 06:50:25 +00:00
platform/x86/amd/pmf: Add PMF TEE interface
AMD PMF driver loads the PMF TA (Trusted Application) into the AMD ASP's (AMD Security Processor) TEE (Trusted Execution Environment). PMF Trusted Application is a secured firmware placed under /lib/firmware/amdtee gets loaded only when the TEE environment is initialized. Add the initial code path to build these pipes. Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> Link: https://lore.kernel.org/r/20231212014705.2017474-2-Shyam-sundar.S-k@amd.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
ed289b98c2
commit
ac052d8c08
5 changed files with 130 additions and 5 deletions
|
@ -9,6 +9,7 @@ config AMD_PMF
|
||||||
depends on POWER_SUPPLY
|
depends on POWER_SUPPLY
|
||||||
depends on AMD_NB
|
depends on AMD_NB
|
||||||
select ACPI_PLATFORM_PROFILE
|
select ACPI_PLATFORM_PROFILE
|
||||||
|
depends on TEE
|
||||||
help
|
help
|
||||||
This driver provides support for the AMD Platform Management Framework.
|
This driver provides support for the AMD Platform Management Framework.
|
||||||
The goal is to enhance end user experience by making AMD PCs smarter,
|
The goal is to enhance end user experience by making AMD PCs smarter,
|
||||||
|
|
|
@ -6,4 +6,5 @@
|
||||||
|
|
||||||
obj-$(CONFIG_AMD_PMF) += amd-pmf.o
|
obj-$(CONFIG_AMD_PMF) += amd-pmf.o
|
||||||
amd-pmf-objs := core.o acpi.o sps.o \
|
amd-pmf-objs := core.o acpi.o sps.o \
|
||||||
auto-mode.o cnqf.o
|
auto-mode.o cnqf.o \
|
||||||
|
tee-if.o
|
||||||
|
|
|
@ -309,13 +309,13 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
|
||||||
dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
|
dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable Auto Mode */
|
if (!amd_pmf_init_smart_pc(dev)) {
|
||||||
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
|
dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
|
||||||
|
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
|
||||||
amd_pmf_init_auto_mode(dev);
|
amd_pmf_init_auto_mode(dev);
|
||||||
dev_dbg(dev->dev, "Auto Mode Init done\n");
|
dev_dbg(dev->dev, "Auto Mode Init done\n");
|
||||||
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
|
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
|
||||||
is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
|
is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
|
||||||
/* Enable Cool n Quiet Framework (CnQF) */
|
|
||||||
ret = amd_pmf_init_cnqf(dev);
|
ret = amd_pmf_init_cnqf(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_warn(dev->dev, "CnQF Init failed\n");
|
dev_warn(dev->dev, "CnQF Init failed\n");
|
||||||
|
@ -330,7 +330,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
|
||||||
amd_pmf_deinit_sps(dev);
|
amd_pmf_deinit_sps(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
|
if (!dev->smart_pc_enabled) {
|
||||||
|
amd_pmf_deinit_smart_pc(dev);
|
||||||
|
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
|
||||||
amd_pmf_deinit_auto_mode(dev);
|
amd_pmf_deinit_auto_mode(dev);
|
||||||
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
|
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
|
||||||
is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
|
is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
|
||||||
|
|
|
@ -179,6 +179,12 @@ struct amd_pmf_dev {
|
||||||
bool cnqf_enabled;
|
bool cnqf_enabled;
|
||||||
bool cnqf_supported;
|
bool cnqf_supported;
|
||||||
struct notifier_block pwr_src_notifier;
|
struct notifier_block pwr_src_notifier;
|
||||||
|
/* Smart PC solution builder */
|
||||||
|
struct tee_context *tee_ctx;
|
||||||
|
struct tee_shm *fw_shm_pool;
|
||||||
|
u32 session_id;
|
||||||
|
void *shbuf;
|
||||||
|
bool smart_pc_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct apmf_sps_prop_granular {
|
struct apmf_sps_prop_granular {
|
||||||
|
@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
|
||||||
struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
|
struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct ta_pmf_shared_memory {
|
||||||
|
int command_id;
|
||||||
|
int resp_id;
|
||||||
|
u32 pmf_result;
|
||||||
|
u32 if_version;
|
||||||
|
};
|
||||||
|
|
||||||
/* Core Layer */
|
/* Core Layer */
|
||||||
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
|
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
|
||||||
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
|
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
|
||||||
|
@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
|
||||||
int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
|
int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
|
||||||
extern const struct attribute_group cnqf_feature_attribute_group;
|
extern const struct attribute_group cnqf_feature_attribute_group;
|
||||||
|
|
||||||
|
/* Smart PC builder Layer */
|
||||||
|
int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
|
||||||
|
void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
|
||||||
#endif /* PMF_H */
|
#endif /* PMF_H */
|
||||||
|
|
105
drivers/platform/x86/amd/pmf/tee-if.c
Normal file
105
drivers/platform/x86/amd/pmf/tee-if.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* AMD Platform Management Framework Driver - TEE Interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023, Advanced Micro Devices, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/tee_drv.h>
|
||||||
|
#include <linux/uuid.h>
|
||||||
|
#include "pmf.h"
|
||||||
|
|
||||||
|
#define MAX_TEE_PARAM 4
|
||||||
|
static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
|
||||||
|
0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
|
||||||
|
|
||||||
|
static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
|
||||||
|
{
|
||||||
|
return ver->impl_id == TEE_IMPL_ID_AMDTEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id)
|
||||||
|
{
|
||||||
|
struct tee_ioctl_open_session_arg sess_arg = {};
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
export_uuid(sess_arg.uuid, &amd_pmf_ta_uuid);
|
||||||
|
sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
|
||||||
|
sess_arg.num_params = 0;
|
||||||
|
|
||||||
|
rc = tee_client_open_session(ctx, &sess_arg, NULL);
|
||||||
|
if (rc < 0 || sess_arg.ret != 0) {
|
||||||
|
pr_err("Failed to open TEE session err:%#x, rc:%d\n", sess_arg.ret, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*id = sess_arg.session;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
|
||||||
|
{
|
||||||
|
u32 size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev->tee_ctx = tee_client_open_context(NULL, amd_pmf_amdtee_ta_match, NULL, NULL);
|
||||||
|
if (IS_ERR(dev->tee_ctx)) {
|
||||||
|
dev_err(dev->dev, "Failed to open TEE context\n");
|
||||||
|
return PTR_ERR(dev->tee_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev->dev, "Failed to open TA session (%d)\n", ret);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = sizeof(struct ta_pmf_shared_memory);
|
||||||
|
dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
|
||||||
|
if (IS_ERR(dev->fw_shm_pool)) {
|
||||||
|
dev_err(dev->dev, "Failed to alloc TEE shared memory\n");
|
||||||
|
ret = PTR_ERR(dev->fw_shm_pool);
|
||||||
|
goto out_sess;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->shbuf = tee_shm_get_va(dev->fw_shm_pool, 0);
|
||||||
|
if (IS_ERR(dev->shbuf)) {
|
||||||
|
dev_err(dev->dev, "Failed to get TEE virtual address\n");
|
||||||
|
ret = PTR_ERR(dev->shbuf);
|
||||||
|
goto out_shm;
|
||||||
|
}
|
||||||
|
dev_dbg(dev->dev, "TEE init done\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_shm:
|
||||||
|
tee_shm_free(dev->fw_shm_pool);
|
||||||
|
out_sess:
|
||||||
|
tee_client_close_session(dev->tee_ctx, dev->session_id);
|
||||||
|
out_ctx:
|
||||||
|
tee_client_close_context(dev->tee_ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
|
||||||
|
{
|
||||||
|
tee_shm_free(dev->fw_shm_pool);
|
||||||
|
tee_client_close_session(dev->tee_ctx, dev->session_id);
|
||||||
|
tee_client_close_context(dev->tee_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
|
||||||
|
{
|
||||||
|
return amd_pmf_tee_init(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
|
||||||
|
{
|
||||||
|
amd_pmf_tee_deinit(dev);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue