new file mode 100644
@@ -0,0 +1,11 @@
+What: /sys/devices/system/node/nodeX/crypto_capable
+Date: September 2021
+Contact: Martin Fernandez <martin.fernandez@eclypsium.com>
+Users: fwupd
+Description:
+ This value is 1 if all system memory is marked with
+ EFI_MEMORY_CPU_CRYPTO, indicating that the system
+ memory is capable of being protected with the CPU’s
+ memory cryptographic capabilities. It is 0
+ otherwise. This attribute will only be available if
+ node X is local.
@@ -20,6 +20,8 @@
#define NODE_MIN_SIZE (4*1024*1024)
extern int numa_off;
+extern bool dummy_numa;
+extern int emu_nid_to_phys[];
/*
* __apicid_to_node[] stores the raw mapping between physical apicid and
@@ -20,6 +20,7 @@
#include "numa_internal.h"
int numa_off;
+bool dummy_numa;
nodemask_t numa_nodes_parsed __initdata;
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
@@ -712,6 +713,8 @@ static int __init dummy_numa_init(void)
node_set(0, numa_nodes_parsed);
numa_add_memblk(0, 0, PFN_PHYS(max_pfn));
+ dummy_numa = true;
+
return 0;
}
@@ -724,6 +727,8 @@ static int __init dummy_numa_init(void)
*/
void __init x86_numa_init(void)
{
+ dummy_numa = false;
+
if (!numa_off) {
#ifdef CONFIG_ACPI_NUMA
if (!numa_init(x86_acpi_numa_init))
@@ -10,7 +10,7 @@
#include "numa_internal.h"
-static int emu_nid_to_phys[MAX_NUMNODES];
+int emu_nid_to_phys[MAX_NUMNODES];
static char *emu_cmdline __initdata;
int __init numa_emu_cmdline(char *str)
@@ -441,6 +441,31 @@ static int __init efi_config_init(const efi_config_table_type_t *arch_tables)
return ret;
}
+enum efi_mem_crypto_t efi_mem_crypto = EFI_MEM_ENCRYPTION_NOT_CAPABLE;
+
+static void __init efi_set_mem_crypto(void)
+{
+ efi_memory_desc_t *md;
+
+ efi_mem_crypto = EFI_MEM_ENCRYPTION_CAPABLE;
+
+ for_each_efi_memory_desc(md) {
+ switch (md->type) {
+ /* System memory after ExitBootServices */
+ case EFI_LOADER_CODE:
+ case EFI_LOADER_DATA:
+ case EFI_BOOT_SERVICES_CODE:
+ case EFI_BOOT_SERVICES_DATA:
+ case EFI_CONVENTIONAL_MEMORY:
+ case EFI_ACPI_RECLAIM_MEMORY:
+ if (!(md->attribute & EFI_MEMORY_CPU_CRYPTO)) {
+ efi_mem_crypto = EFI_MEM_ENCRYPTION_NOT_CAPABLE;
+ return;
+ }
+ }
+ }
+}
+
void __init efi_init(void)
{
if (IS_ENABLED(CONFIG_X86_32) &&
@@ -494,6 +519,8 @@ void __init efi_init(void)
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
efi_clean_memmap();
+ efi_set_mem_crypto();
+
if (efi_enabled(EFI_DBG))
efi_print_memmap();
}
@@ -20,6 +20,7 @@
#include <linux/pm_runtime.h>
#include <linux/swap.h>
#include <linux/slab.h>
+#include <linux/efi.h>
static struct bus_type node_subsys = {
.name = "node",
@@ -68,6 +69,15 @@ static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
static BIN_ATTR_RO(cpulist, 0);
+#if defined(CONFIG_NUMA) && defined(CONFIG_EFI)
+static ssize_t crypto_capable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", efi_mem_crypto);
+}
+static DEVICE_ATTR_RO(crypto_capable);
+#endif
+
/**
* struct node_access_nodes - Access class device to hold user visible
* relationships to other nodes.
@@ -584,6 +594,23 @@ static const struct attribute_group *node_dev_groups[] = {
NULL
};
+#if defined(CONFIG_NUMA) && defined(CONFIG_EFI)
+static struct attribute *node_dev_crypto_attrs[] = {
+ &dev_attr_crypto_capable.attr,
+ NULL
+};
+
+static const struct attribute_group node_dev_crypto_group = {
+ .attrs = node_dev_crypto_attrs,
+};
+
+static const struct attribute_group *node_dev_crypto_groups[] = {
+ &node_dev_group,
+ &node_dev_crypto_group,
+ NULL
+};
+#endif
+
#ifdef CONFIG_HUGETLBFS
/*
* hugetlbfs per node attributes registration interface:
@@ -644,6 +671,21 @@ static void node_device_release(struct device *dev)
kfree(node);
}
+#if defined(CONFIG_NUMA) && defined(CONFIG_EFI)
+static const struct attribute_group **select_attr_groups(bool cpu_local)
+{
+ if (cpu_local)
+ return node_dev_crypto_groups;
+ else
+ return node_dev_groups;
+}
+#else
+static const struct attribute_group **select_attr_groups(bool cpu_local)
+{
+ return node_dev_groups;
+}
+#endif
+
/*
* register_node - Setup a sysfs device for a node.
* @num - Node number to use when creating the device.
@@ -657,7 +699,8 @@ static int register_node(struct node *node, int num)
node->dev.id = num;
node->dev.bus = &node_subsys;
node->dev.release = node_device_release;
- node->dev.groups = node_dev_groups;
+ node->dev.groups = select_attr_groups(node->cpu_local);
+
error = device_register(&node->dev);
if (error)
@@ -974,6 +1017,39 @@ static void init_node_hugetlb_work(int nid) { }
#endif
+#ifdef CONFIG_NUMA
+#ifdef CONFIG_NUMA_EMU
+static int get_real_nid(int nid)
+{
+ return emu_nid_to_phys[nid];
+}
+#else
+static int get_real_nid(int nid)
+{
+ return nid;
+}
+#endif
+
+static void set_cpu_local(int nid)
+{
+ int real_nid;
+ bool cpu_local;
+
+ real_nid = get_real_nid(nid);
+
+#ifdef CONFIG_ACPI_NUMA
+ cpu_local =
+ dummy_numa ? real_nid == 0 : node_to_pxm(real_nid) != PXM_INVAL;
+#else
+ cpu_local = real_nid == 0;
+#endif
+
+ node_devices[nid]->cpu_local = cpu_local;
+}
+#else
+#define set_cpu_local(nid)
+#endif /* CONFIG_NUMA */
+
int __register_one_node(int nid)
{
int error;
@@ -983,6 +1059,8 @@ int __register_one_node(int nid)
if (!node_devices[nid])
return -ENOMEM;
+ set_cpu_local(nid);
+
error = register_node(node_devices[nid], nid);
/* link cpu under this node */
@@ -1282,4 +1282,11 @@ static inline struct efi_mokvar_table_entry *efi_mokvar_entry_find(
}
#endif
+enum efi_mem_crypto_t {
+ EFI_MEM_ENCRYPTION_NOT_CAPABLE,
+ EFI_MEM_ENCRYPTION_CAPABLE,
+};
+
+extern enum efi_mem_crypto_t efi_mem_crypto;
+
#endif /* _LINUX_EFI_H */
@@ -19,6 +19,8 @@
#include <linux/cpumask.h>
#include <linux/list.h>
#include <linux/workqueue.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_numa.h>
/**
* struct node_hmem_attrs - heterogeneous memory performance attributes
@@ -92,6 +94,9 @@ struct node {
struct list_head cache_attrs;
struct device *cache_dev;
#endif
+#ifdef CONFIG_NUMA
+ bool cpu_local;
+#endif
};
struct memory_block;