@@ -2,6 +2,7 @@
/* Documentation/x86/mktme_keys.rst */
+#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/key.h>
#include <linux/key-type.h>
@@ -17,6 +18,8 @@
static DEFINE_SPINLOCK(mktme_lock);
struct kmem_cache *mktme_prog_cache; /* Hardware programming cache */
+unsigned long *mktme_target_map; /* Pconfig programming targets */
+cpumask_var_t mktme_leadcpus; /* One lead CPU per pconfig target */
/* 1:1 Mapping between Userspace Keys (struct key) and Hardware KeyIDs */
struct mktme_mapping {
@@ -303,6 +306,33 @@ struct key_type key_type_mktme = {
.destroy = mktme_destroy_key,
};
+static void mktme_update_pconfig_targets(void)
+{
+ int cpu, target_id;
+
+ cpumask_clear(mktme_leadcpus);
+ bitmap_clear(mktme_target_map, 0, sizeof(mktme_target_map));
+
+ for_each_online_cpu(cpu) {
+ target_id = topology_physical_package_id(cpu);
+ if (!__test_and_set_bit(target_id, mktme_target_map))
+ __cpumask_set_cpu(cpu, mktme_leadcpus);
+ }
+}
+
+static int mktme_alloc_pconfig_targets(void)
+{
+ if (!alloc_cpumask_var(&mktme_leadcpus, GFP_KERNEL))
+ return -ENOMEM;
+
+ mktme_target_map = bitmap_alloc(topology_max_packages(), GFP_KERNEL);
+ if (!mktme_target_map) {
+ free_cpumask_var(mktme_leadcpus);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
static int __init init_mktme(void)
{
int ret;
@@ -320,9 +350,21 @@ static int __init init_mktme(void)
if (!mktme_prog_cache)
goto free_map;
+ /* Hardware programming targets */
+ if (mktme_alloc_pconfig_targets())
+ goto free_cache;
+
+ /* Initialize first programming targets */
+ mktme_update_pconfig_targets();
+
ret = register_key_type(&key_type_mktme);
if (!ret)
return ret; /* SUCCESS */
+
+ free_cpumask_var(mktme_leadcpus);
+ bitmap_free(mktme_target_map);
+free_cache:
+ kmem_cache_destroy(mktme_prog_cache);
free_map:
kvfree(mktme_map);