* [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption
@ 2021-11-24 20:34 Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 1/5] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Martin Fernandez @ 2021-11-24 20:34 UTC (permalink / raw)
To: linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Martin Fernandez
Show for each node if every memory descriptor in that node has the
EFI_MEMORY_CPU_CRYPTO attribute.
fwupd project plans to use it as part of a check to see if the users
have properly configured memory hardware encryption capabilities. It's
planned to make it part of a specification that can be passed to
people purchasing hardware. It's called Host Security ID:
https://fwupd.github.io/libfwupdplugin/hsi.html
This also can be useful in the future if NUMA decides to prioritize
nodes that are able to do encryption.
Changes since v1:
Modify __e820__range_update to update the crypto capabilities of a
range; now this function will change the crypto capability of a range
if it's called with the same old_type and new_type. Rework
efi_mark_e820_regions_as_crypto_capable based on this.
Update do_add_efi_memmap to mark the regions as it creates them.
Change the type of crypto_capable in e820_entry from bool to u8.
Fix e820__update_table changes.
Remove memblock_add_crypto_capable. Now you have to add the region and
mark it then.
Better place for crypto_capable in pglist_data.
Martin Fernandez (5):
mm/memblock: Tag memblocks with crypto capabilities
mm/mmzone: Tag pg_data_t with crypto capabilities
x86/e820: Tag e820_entry with crypto capabilities
x86/efi: Tag e820_entries as crypto capable from EFI memmap
drivers/node: Show in sysfs node's crypto capabilities
Documentation/ABI/testing/sysfs-devices-node | 10 ++++
arch/x86/include/asm/e820/api.h | 1 +
arch/x86/include/asm/e820/types.h | 1 +
arch/x86/kernel/e820.c | 58 ++++++++++++++++----
arch/x86/platform/efi/efi.c | 25 +++++++++
drivers/base/node.c | 10 ++++
include/linux/memblock.h | 5 ++
include/linux/mmzone.h | 3 +
mm/memblock.c | 49 +++++++++++++++++
mm/page_alloc.c | 1 +
10 files changed, 152 insertions(+), 11 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-devices-node
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/5] mm/memblock: Tag memblocks with crypto capabilities
2021-11-24 20:34 [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
@ 2021-11-24 20:34 ` Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 2/5] mm/mmzone: Tag pg_data_t " Martin Fernandez
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Martin Fernandez @ 2021-11-24 20:34 UTC (permalink / raw)
To: linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Martin Fernandez
Add the capability to mark regions of the memory memory_type able of
hardware memory encryption.
Also add the capability to query if all regions of a memory node are
able to do hardware memory encryption to call it when initializing the
nodes.
Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
include/linux/memblock.h | 5 ++++
mm/memblock.c | 49 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 34de69b3b8ba..a54665863f80 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -31,6 +31,7 @@ extern unsigned long long max_possible_pfn;
* @MEMBLOCK_HOTPLUG: hotpluggable region
* @MEMBLOCK_MIRROR: mirrored region
* @MEMBLOCK_NOMAP: don't add to kernel direct mapping and treat as
+ * @MEMBLOCK_CRYPTO_CAPABLE: capable of hardware encryption
* reserved in the memory map; refer to memblock_mark_nomap() description
* for further details
*/
@@ -39,6 +40,7 @@ enum memblock_flags {
MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
MEMBLOCK_MIRROR = 0x2, /* mirrored region */
MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */
+ MEMBLOCK_CRYPTO_CAPABLE = 0x8, /* capable of hardware encryption */
};
/**
@@ -111,6 +113,9 @@ int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
void memblock_trim_memory(phys_addr_t align);
bool memblock_overlaps_region(struct memblock_type *type,
phys_addr_t base, phys_addr_t size);
+bool memblock_node_is_crypto_capable(int nid);
+int memblock_mark_crypto_capable(phys_addr_t base, phys_addr_t size);
+int memblock_clear_crypto_capable(phys_addr_t base, phys_addr_t size);
int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 5096500b2647..cd5553c3df5a 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -191,6 +191,27 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
return i < type->cnt;
}
+/**
+ * memblock_node_is_crypto_capable - get if whole node is capable
+ * of encryption
+ * @nid: number of node
+ *
+ * Iterate over all memory memblock_type and find if all regions under
+ * node @nid are capable of hardware encryption.
+ */
+bool __init_memblock memblock_node_is_crypto_capable(int nid)
+{
+ struct memblock_region *region;
+
+ for_each_mem_region(region) {
+ if ((memblock_get_region_node(region) == nid) &&
+ !(region->flags & MEMBLOCK_CRYPTO_CAPABLE))
+ return false;
+ }
+
+ return true;
+}
+
/**
* __memblock_find_range_bottom_up - find free area utility in bottom-up
* @start: start of candidate range
@@ -884,6 +905,34 @@ static int __init_memblock memblock_setclr_flag(phys_addr_t base,
return 0;
}
+/**
+ * memblock_mark_crypto_capable - Mark memory regions capable of hardware
+ * encryption with flag MEMBLOCK_CRYPTO_CAPABLE.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_crypto_capable(phys_addr_t base,
+ phys_addr_t size)
+{
+ return memblock_setclr_flag(base, size, 1, MEMBLOCK_CRYPTO_CAPABLE);
+}
+
+/**
+ * memblock_clear_crypto_capable - Clear flag MEMBLOCK_CRYPTO for a
+ * specified region.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_clear_crypto_capable(phys_addr_t base,
+ phys_addr_t size)
+{
+ return memblock_setclr_flag(base, size, 0, MEMBLOCK_CRYPTO_CAPABLE);
+}
+
/**
* memblock_mark_hotplug - Mark hotpluggable memory with flag MEMBLOCK_HOTPLUG.
* @base: the base phys addr of the region
--
2.30.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/5] mm/mmzone: Tag pg_data_t with crypto capabilities
2021-11-24 20:34 [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 1/5] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
@ 2021-11-24 20:34 ` Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 3/5] x86/e820: Tag e820_entry " Martin Fernandez
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Martin Fernandez @ 2021-11-24 20:34 UTC (permalink / raw)
To: linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Martin Fernandez
Add a new member in the pg_data_t struct tell whether the node
corresponding to that pg_data_t is able to do hardware memory encryption.
This will be read from sysfs.
Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
include/linux/mmzone.h | 3 +++
mm/page_alloc.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 6a1d79d84675..e437d7ebd8cc 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -855,6 +855,9 @@ typedef struct pglist_data {
struct task_struct *kcompactd;
bool proactive_compact_trigger;
#endif
+
+ bool crypto_capable;
+
/*
* This is a per-node reserve of pages that are not available
* to userspace allocations.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b37435c274cf..a19d95bb5c0f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7575,6 +7575,7 @@ static void __init free_area_init_node(int nid)
pgdat->node_id = nid;
pgdat->node_start_pfn = start_pfn;
pgdat->per_cpu_nodestats = NULL;
+ pgdat->crypto_capable = memblock_node_is_crypto_capable(nid);
pr_info("Initmem setup node %d [mem %#018Lx-%#018Lx]\n", nid,
(u64)start_pfn << PAGE_SHIFT,
--
2.30.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/5] x86/e820: Tag e820_entry with crypto capabilities
2021-11-24 20:34 [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 1/5] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 2/5] mm/mmzone: Tag pg_data_t " Martin Fernandez
@ 2021-11-24 20:34 ` Martin Fernandez
2021-11-25 7:06 ` Dov Murik
2021-11-24 20:34 ` [PATCH v2 4/5] x86/efi: Tag e820_entries as crypto capable from EFI memmap Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 5/5] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
4 siblings, 1 reply; 8+ messages in thread
From: Martin Fernandez @ 2021-11-24 20:34 UTC (permalink / raw)
To: linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Martin Fernandez
Add a new member in e820_entry to hold whether an entry is able to do
hardware memory encryption or not.
Add a new argument to __e820__range_add to accept this new
crypto_capable.
Add a new argument to __e820__update_range to be able to change a
region's crypto_capable member. Also, change its behavior a little,
before if you wanted to update a region with its same type it was a
BUG_ON; now if you call it with both old_type and new_type equals,
then the function won't change the types, just crypto_capable.
Change e820__update_table to handle merging and overlap problems
taking into account crypto_capable.
Add a function to mark a range as crypto, using __e820__range_update
in the background. This will be called when initializing EFI.
Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
arch/x86/include/asm/e820/api.h | 1 +
arch/x86/include/asm/e820/types.h | 1 +
arch/x86/kernel/e820.c | 58 +++++++++++++++++++++++++------
3 files changed, 49 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h
index e8f58ddd06d9..fdfe1c37dcfc 100644
--- a/arch/x86/include/asm/e820/api.h
+++ b/arch/x86/include/asm/e820/api.h
@@ -17,6 +17,7 @@ extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
extern void e820__range_add (u64 start, u64 size, enum e820_type type);
extern u64 e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
extern u64 e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type);
+extern u64 e820__range_mark_as_crypto(u64 start, u64 size);
extern void e820__print_table(char *who);
extern int e820__update_table(struct e820_table *table);
diff --git a/arch/x86/include/asm/e820/types.h b/arch/x86/include/asm/e820/types.h
index 314f75d886d0..7b510dffd3b9 100644
--- a/arch/x86/include/asm/e820/types.h
+++ b/arch/x86/include/asm/e820/types.h
@@ -56,6 +56,7 @@ struct e820_entry {
u64 addr;
u64 size;
enum e820_type type;
+ u8 crypto_capable;
} __attribute__((packed));
/*
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index bc0657f0deed..4581598690a9 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -163,7 +163,7 @@ int e820__get_entry_type(u64 start, u64 end)
/*
* Add a memory region to the kernel E820 map.
*/
-static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type)
+static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type, u8 crypto_capable)
{
int x = table->nr_entries;
@@ -176,12 +176,13 @@ static void __init __e820__range_add(struct e820_table *table, u64 start, u64 si
table->entries[x].addr = start;
table->entries[x].size = size;
table->entries[x].type = type;
+ table->entries[x].crypto_capable = crypto_capable;
table->nr_entries++;
}
void __init e820__range_add(u64 start, u64 size, enum e820_type type)
{
- __e820__range_add(e820_table, start, size, type);
+ __e820__range_add(e820_table, start, size, type, 0);
}
static void __init e820_print_type(enum e820_type type)
@@ -211,6 +212,8 @@ void __init e820__print_table(char *who)
e820_table->entries[i].addr + e820_table->entries[i].size - 1);
e820_print_type(e820_table->entries[i].type);
+ if (e820_table->entries[i].crypto_capable)
+ pr_cont("; crypto-capable");
pr_cont("\n");
}
}
@@ -327,6 +330,7 @@ int __init e820__update_table(struct e820_table *table)
unsigned long long last_addr;
u32 new_nr_entries, overlap_entries;
u32 i, chg_idx, chg_nr;
+ u8 current_crypto, last_crypto;
/* If there's only one memory region, don't bother: */
if (table->nr_entries < 2)
@@ -367,6 +371,7 @@ int __init e820__update_table(struct e820_table *table)
new_nr_entries = 0; /* Index for creating new map entries */
last_type = 0; /* Start with undefined memory type */
last_addr = 0; /* Start with 0 as last starting address */
+ last_crypto = 0;
/* Loop through change-points, determining effect on the new map: */
for (chg_idx = 0; chg_idx < chg_nr; chg_idx++) {
@@ -388,13 +393,17 @@ int __init e820__update_table(struct e820_table *table)
* 1=usable, 2,3,4,4+=unusable)
*/
current_type = 0;
+ current_crypto = 1;
for (i = 0; i < overlap_entries; i++) {
+ current_crypto = current_crypto && overlap_list[i]->crypto_capable;
if (overlap_list[i]->type > current_type)
current_type = overlap_list[i]->type;
}
/* Continue building up new map based on this information: */
- if (current_type != last_type || e820_nomerge(current_type)) {
+ if (current_type != last_type ||
+ current_crypto != last_crypto ||
+ e820_nomerge(current_type)) {
if (last_type != 0) {
new_entries[new_nr_entries].size = change_point[chg_idx]->addr - last_addr;
/* Move forward only if the new size was non-zero: */
@@ -406,9 +415,12 @@ int __init e820__update_table(struct e820_table *table)
if (current_type != 0) {
new_entries[new_nr_entries].addr = change_point[chg_idx]->addr;
new_entries[new_nr_entries].type = current_type;
+ new_entries[new_nr_entries].crypto_capable = current_crypto;
+
last_addr = change_point[chg_idx]->addr;
}
last_type = current_type;
+ last_crypto = current_crypto;
}
}
@@ -459,14 +471,20 @@ static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entr
return __append_e820_table(entries, nr_entries);
}
+/*
+ * Update a memory range.
+ *
+ * If old_type and new_type are the same then ignore the types and
+ * just change crypto_capable.
+ */
static u64 __init
-__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
+__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type, u8 crypto_capable)
{
u64 end;
unsigned int i;
u64 real_updated_size = 0;
- BUG_ON(old_type == new_type);
+ bool update_crypto = new_type == old_type;
if (size > (ULLONG_MAX - start))
size = ULLONG_MAX - start;
@@ -476,6 +494,8 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
e820_print_type(old_type);
pr_cont(" ==> ");
e820_print_type(new_type);
+ if (crypto_capable)
+ pr_cont("; crypto-capable");
pr_cont("\n");
for (i = 0; i < table->nr_entries; i++) {
@@ -483,22 +503,27 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
u64 final_start, final_end;
u64 entry_end;
- if (entry->type != old_type)
+ if (entry->type != old_type && !update_crypto)
continue;
+ if (update_crypto)
+ new_type = entry->type;
+
entry_end = entry->addr + entry->size;
/* Completely covered by new range? */
if (entry->addr >= start && entry_end <= end) {
entry->type = new_type;
+ entry->crypto_capable = crypto_capable;
real_updated_size += entry->size;
continue;
}
/* New range is completely covered? */
if (entry->addr < start && entry_end > end) {
- __e820__range_add(table, start, size, new_type);
- __e820__range_add(table, end, entry_end - end, entry->type);
+ __e820__range_add(table, start, size, new_type, crypto_capable);
+ __e820__range_add(table, end, entry_end - end,
+ entry->type, entry->crypto_capable);
entry->size = start - entry->addr;
real_updated_size += size;
continue;
@@ -510,7 +535,8 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
if (final_start >= final_end)
continue;
- __e820__range_add(table, final_start, final_end - final_start, new_type);
+ __e820__range_add(table, final_start, final_end - final_start,
+ new_type, crypto_capable);
real_updated_size += final_end - final_start;
@@ -527,14 +553,19 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
return real_updated_size;
}
+u64 __init e820__range_mark_as_crypto(u64 start, u64 size)
+{
+ return __e820__range_update(e820_table, start, size, 0, 0, true);
+}
+
u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
{
- return __e820__range_update(e820_table, start, size, old_type, new_type);
+ return __e820__range_update(e820_table, start, size, old_type, new_type, false);
}
static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
{
- return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
+ return __e820__range_update(e820_table_kexec, start, size, old_type, new_type, false);
}
/* Remove a range of memory from the E820 table: */
@@ -573,6 +604,9 @@ u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool
/* Is the new range completely covered? */
if (entry->addr < start && entry_end > end) {
e820__range_add(end, entry_end - end, entry->type);
+ if (entry->crypto_capable)
+ e820__range_mark_as_crypto(end, entry_end - end);
+
entry->size = start - entry->addr;
real_removed_size += size;
continue;
@@ -1322,6 +1356,8 @@ void __init e820__memblock_setup(void)
continue;
memblock_add(entry->addr, entry->size);
+ if (entry->crypto_capable)
+ memblock_mark_crypto_capable(entry->addr, entry->size);
}
/* Throw away partial pages: */
--
2.30.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/5] x86/efi: Tag e820_entries as crypto capable from EFI memmap
2021-11-24 20:34 [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
` (2 preceding siblings ...)
2021-11-24 20:34 ` [PATCH v2 3/5] x86/e820: Tag e820_entry " Martin Fernandez
@ 2021-11-24 20:34 ` Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 5/5] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
4 siblings, 0 replies; 8+ messages in thread
From: Martin Fernandez @ 2021-11-24 20:34 UTC (permalink / raw)
To: linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Martin Fernandez
Add a function to iterate over the EFI Memory Map and mark the regions
tagged with EFI_MEMORY_CPU_CRYPTO in the e820_table; and call it from
efi_init if add_efi_memmap is disabled.
Also modify do_add_efi_memmap to mark the regions there.
Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
arch/x86/platform/efi/efi.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 147c30a81f15..8f52cde61688 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -184,6 +184,8 @@ static void __init do_add_efi_memmap(void)
}
e820__range_add(start, size, e820_type);
+ if (md->attribute & EFI_MEMORY_CPU_CRYPTO)
+ e820__range_mark_as_crypto(start, size);
}
e820__update_table(e820_table);
}
@@ -441,6 +443,22 @@ static int __init efi_config_init(const efi_config_table_type_t *arch_tables)
return ret;
}
+static void __init efi_mark_e820_regions_as_crypto_capable(void)
+{
+ efi_memory_desc_t *md;
+
+ for_each_efi_memory_desc(md) {
+ if (md->attribute & EFI_MEMORY_CPU_CRYPTO)
+ e820__range_mark_as_crypto(md->phys_addr, md->num_pages << EFI_PAGE_SHIFT);
+ }
+
+ /*
+ * We added and modified regions so it's good to update the
+ * table to merge/sort
+ */
+ e820__update_table(e820_table);
+}
+
void __init efi_init(void)
{
if (IS_ENABLED(CONFIG_X86_32) &&
@@ -494,6 +512,13 @@ void __init efi_init(void)
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
efi_clean_memmap();
+ /*
+ * If add_efi_memmap then there is no need to mark the regions
+ * again
+ */
+ if (!add_efi_memmap)
+ efi_mark_e820_regions_as_crypto_capable();
+
if (efi_enabled(EFI_DBG))
efi_print_memmap();
}
--
2.30.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 5/5] drivers/node: Show in sysfs node's crypto capabilities
2021-11-24 20:34 [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
` (3 preceding siblings ...)
2021-11-24 20:34 ` [PATCH v2 4/5] x86/efi: Tag e820_entries as crypto capable from EFI memmap Martin Fernandez
@ 2021-11-24 20:34 ` Martin Fernandez
4 siblings, 0 replies; 8+ messages in thread
From: Martin Fernandez @ 2021-11-24 20:34 UTC (permalink / raw)
To: linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Martin Fernandez
Show in each node in sysfs if its memory is able to do be encrypted by
the CPU, ie. if all its memory is marked with EFI_MEMORY_CPU_CRYPTO in
the EFI memory map.
Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
Documentation/ABI/testing/sysfs-devices-node | 10 ++++++++++
drivers/base/node.c | 10 ++++++++++
2 files changed, 20 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-devices-node
diff --git a/Documentation/ABI/testing/sysfs-devices-node b/Documentation/ABI/testing/sysfs-devices-node
new file mode 100644
index 000000000000..ab46fdd3f6a8
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-node
@@ -0,0 +1,10 @@
+What: /sys/devices/system/node/nodeX/crypto_capable
+Date: October 2021
+Contact: Martin Fernandez <martin.fernandez@eclypsium.com>
+Users: fwupd
+Description:
+ This value is 1 if all system memory in this node 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.
\ No newline at end of file
diff --git a/drivers/base/node.c b/drivers/base/node.c
index c56d34f8158f..4e6ef86f4523 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -560,11 +560,21 @@ static ssize_t node_read_distance(struct device *dev,
}
static DEVICE_ATTR(distance, 0444, node_read_distance, NULL);
+static ssize_t crypto_capable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pglist_data *pgdat = NODE_DATA(dev->id);
+
+ return sysfs_emit(buf, "%d\n", pgdat->crypto_capable);
+}
+static DEVICE_ATTR_RO(crypto_capable);
+
static struct attribute *node_dev_attrs[] = {
&dev_attr_meminfo.attr,
&dev_attr_numastat.attr,
&dev_attr_distance.attr,
&dev_attr_vmstat.attr,
+ &dev_attr_crypto_capable.attr,
NULL
};
--
2.30.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 3/5] x86/e820: Tag e820_entry with crypto capabilities
2021-11-24 20:34 ` [PATCH v2 3/5] x86/e820: Tag e820_entry " Martin Fernandez
@ 2021-11-25 7:06 ` Dov Murik
2021-11-25 18:12 ` Martin Fernandez
0 siblings, 1 reply; 8+ messages in thread
From: Dov Murik @ 2021-11-25 7:06 UTC (permalink / raw)
To: Martin Fernandez, linux-efi, platform-driver-x86, linux-mm
Cc: tglx, mingo, bp, x86, hpa, dave.hansen, luto, peterz, ardb,
dvhart, andy, gregkh, rafael, daniel.gutson, hughsient,
alison.schofield, Dov Murik
On 24/11/2021 22:34, Martin Fernandez wrote:
> Add a new member in e820_entry to hold whether an entry is able to do
> hardware memory encryption or not.
>
> Add a new argument to __e820__range_add to accept this new
> crypto_capable.
>
> Add a new argument to __e820__update_range to be able to change a
> region's crypto_capable member. Also, change its behavior a little,
> before if you wanted to update a region with its same type it was a
> BUG_ON; now if you call it with both old_type and new_type equals,
> then the function won't change the types, just crypto_capable.
>
> Change e820__update_table to handle merging and overlap problems
> taking into account crypto_capable.
>
> Add a function to mark a range as crypto, using __e820__range_update
> in the background. This will be called when initializing EFI.
>
> Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
> ---
> arch/x86/include/asm/e820/api.h | 1 +
> arch/x86/include/asm/e820/types.h | 1 +
> arch/x86/kernel/e820.c | 58 +++++++++++++++++++++++++------
> 3 files changed, 49 insertions(+), 11 deletions(-)
>
> diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h
> index e8f58ddd06d9..fdfe1c37dcfc 100644
> --- a/arch/x86/include/asm/e820/api.h
> +++ b/arch/x86/include/asm/e820/api.h
> @@ -17,6 +17,7 @@ extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
> extern void e820__range_add (u64 start, u64 size, enum e820_type type);
> extern u64 e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
> extern u64 e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type);
> +extern u64 e820__range_mark_as_crypto(u64 start, u64 size);
I suggest: e820__range_mark_as_crypto_capable
(as you do in other function and field names)
>
> extern void e820__print_table(char *who);
> extern int e820__update_table(struct e820_table *table);
> diff --git a/arch/x86/include/asm/e820/types.h b/arch/x86/include/asm/e820/types.h
> index 314f75d886d0..7b510dffd3b9 100644
> --- a/arch/x86/include/asm/e820/types.h
> +++ b/arch/x86/include/asm/e820/types.h
> @@ -56,6 +56,7 @@ struct e820_entry {
> u64 addr;
> u64 size;
> enum e820_type type;
> + u8 crypto_capable;
> } __attribute__((packed));
>
> /*
> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
> index bc0657f0deed..4581598690a9 100644
> --- a/arch/x86/kernel/e820.c
> +++ b/arch/x86/kernel/e820.c
> @@ -163,7 +163,7 @@ int e820__get_entry_type(u64 start, u64 end)
> /*
> * Add a memory region to the kernel E820 map.
> */
> -static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type)
> +static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type, u8 crypto_capable)
> {
> int x = table->nr_entries;
>
> @@ -176,12 +176,13 @@ static void __init __e820__range_add(struct e820_table *table, u64 start, u64 si
> table->entries[x].addr = start;
> table->entries[x].size = size;
> table->entries[x].type = type;
> + table->entries[x].crypto_capable = crypto_capable;
> table->nr_entries++;
> }
>
> void __init e820__range_add(u64 start, u64 size, enum e820_type type)
> {
> - __e820__range_add(e820_table, start, size, type);
> + __e820__range_add(e820_table, start, size, type, 0);
> }
>
> static void __init e820_print_type(enum e820_type type)
> @@ -211,6 +212,8 @@ void __init e820__print_table(char *who)
> e820_table->entries[i].addr + e820_table->entries[i].size - 1);
>
> e820_print_type(e820_table->entries[i].type);
> + if (e820_table->entries[i].crypto_capable)
> + pr_cont("; crypto-capable");
> pr_cont("\n");
> }
> }
> @@ -327,6 +330,7 @@ int __init e820__update_table(struct e820_table *table)
> unsigned long long last_addr;
> u32 new_nr_entries, overlap_entries;
> u32 i, chg_idx, chg_nr;
> + u8 current_crypto, last_crypto;
>
> /* If there's only one memory region, don't bother: */
> if (table->nr_entries < 2)
> @@ -367,6 +371,7 @@ int __init e820__update_table(struct e820_table *table)
> new_nr_entries = 0; /* Index for creating new map entries */
> last_type = 0; /* Start with undefined memory type */
> last_addr = 0; /* Start with 0 as last starting address */
> + last_crypto = 0;
>
> /* Loop through change-points, determining effect on the new map: */
> for (chg_idx = 0; chg_idx < chg_nr; chg_idx++) {
> @@ -388,13 +393,17 @@ int __init e820__update_table(struct e820_table *table)
> * 1=usable, 2,3,4,4+=unusable)
> */
> current_type = 0;
> + current_crypto = 1;
> for (i = 0; i < overlap_entries; i++) {
> + current_crypto = current_crypto && overlap_list[i]->crypto_capable;
> if (overlap_list[i]->type > current_type)
> current_type = overlap_list[i]->type;
> }
>
> /* Continue building up new map based on this information: */
> - if (current_type != last_type || e820_nomerge(current_type)) {
> + if (current_type != last_type ||
> + current_crypto != last_crypto ||
> + e820_nomerge(current_type)) {
> if (last_type != 0) {
> new_entries[new_nr_entries].size = change_point[chg_idx]->addr - last_addr;
> /* Move forward only if the new size was non-zero: */
> @@ -406,9 +415,12 @@ int __init e820__update_table(struct e820_table *table)
> if (current_type != 0) {
> new_entries[new_nr_entries].addr = change_point[chg_idx]->addr;
> new_entries[new_nr_entries].type = current_type;
> + new_entries[new_nr_entries].crypto_capable = current_crypto;
> +
> last_addr = change_point[chg_idx]->addr;
> }
> last_type = current_type;
> + last_crypto = current_crypto;
> }
> }
>
> @@ -459,14 +471,20 @@ static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entr
> return __append_e820_table(entries, nr_entries);
> }
>
> +/*
> + * Update a memory range.
> + *
> + * If old_type and new_type are the same then ignore the types and
> + * just change crypto_capable.
> + */
> static u64 __init
> -__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
> +__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type, u8 crypto_capable)
> {
> u64 end;
> unsigned int i;
> u64 real_updated_size = 0;
>
> - BUG_ON(old_type == new_type);
> + bool update_crypto = new_type == old_type;
>
> if (size > (ULLONG_MAX - start))
> size = ULLONG_MAX - start;
> @@ -476,6 +494,8 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
> e820_print_type(old_type);
> pr_cont(" ==> ");
> e820_print_type(new_type);
> + if (crypto_capable)
> + pr_cont("; crypto-capable");
> pr_cont("\n");
>
> for (i = 0; i < table->nr_entries; i++) {
> @@ -483,22 +503,27 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
> u64 final_start, final_end;
> u64 entry_end;
>
> - if (entry->type != old_type)
> + if (entry->type != old_type && !update_crypto)
> continue;
>
> + if (update_crypto)
> + new_type = entry->type;
> +
> entry_end = entry->addr + entry->size;
>
> /* Completely covered by new range? */
> if (entry->addr >= start && entry_end <= end) {
> entry->type = new_type;
> + entry->crypto_capable = crypto_capable;
> real_updated_size += entry->size;
> continue;
> }
>
> /* New range is completely covered? */
> if (entry->addr < start && entry_end > end) {
> - __e820__range_add(table, start, size, new_type);
> - __e820__range_add(table, end, entry_end - end, entry->type);
> + __e820__range_add(table, start, size, new_type, crypto_capable);
> + __e820__range_add(table, end, entry_end - end,
> + entry->type, entry->crypto_capable);
> entry->size = start - entry->addr;
> real_updated_size += size;
> continue;
> @@ -510,7 +535,8 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
> if (final_start >= final_end)
> continue;
>
> - __e820__range_add(table, final_start, final_end - final_start, new_type);
> + __e820__range_add(table, final_start, final_end - final_start,
> + new_type, crypto_capable);
>
> real_updated_size += final_end - final_start;
>
> @@ -527,14 +553,19 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_ty
> return real_updated_size;
> }
>
> +u64 __init e820__range_mark_as_crypto(u64 start, u64 size)
> +{
> + return __e820__range_update(e820_table, start, size, 0, 0, true);
> +}
> +
> u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
> {
> - return __e820__range_update(e820_table, start, size, old_type, new_type);
> + return __e820__range_update(e820_table, start, size, old_type, new_type, false);
> }
>
> static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
> {
> - return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
> + return __e820__range_update(e820_table_kexec, start, size, old_type, new_type, false);
> }
>
> /* Remove a range of memory from the E820 table: */
> @@ -573,6 +604,9 @@ u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool
> /* Is the new range completely covered? */
> if (entry->addr < start && entry_end > end) {
> e820__range_add(end, entry_end - end, entry->type);
> + if (entry->crypto_capable)
> + e820__range_mark_as_crypto(end, entry_end - end);
> +
Why introduce this new function call instead of adding an extra
'crypto_capable' argument to e820__range_add() ?
-Dov
> entry->size = start - entry->addr;
> real_removed_size += size;
> continue;
> @@ -1322,6 +1356,8 @@ void __init e820__memblock_setup(void)
> continue;
>
> memblock_add(entry->addr, entry->size);
> + if (entry->crypto_capable)
> + memblock_mark_crypto_capable(entry->addr, entry->size);
> }
>
> /* Throw away partial pages: */
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 3/5] x86/e820: Tag e820_entry with crypto capabilities
2021-11-25 7:06 ` Dov Murik
@ 2021-11-25 18:12 ` Martin Fernandez
0 siblings, 0 replies; 8+ messages in thread
From: Martin Fernandez @ 2021-11-25 18:12 UTC (permalink / raw)
To: Dov Murik
Cc: linux-efi, platform-driver-x86, linux-mm, tglx, mingo, bp, x86,
hpa, dave.hansen, luto, peterz, ardb, dvhart, andy, gregkh,
rafael, daniel.gutson, hughsient, alison.schofield
On 11/25/21, Dov Murik <dovmurik@linux.ibm.com> wrote:
> On 24/11/2021 22:34, Martin Fernandez wrote:
>> +extern u64 e820__range_mark_as_crypto(u64 start, u64 size);
>
> I suggest: e820__range_mark_as_crypto_capable
> (as you do in other function and field names)
>
Yes, good catch. Thanks.
>> /* Remove a range of memory from the E820 table: */
>> @@ -573,6 +604,9 @@ u64 __init e820__range_remove(u64 start, u64 size,
>> enum e820_type old_type, bool
>> /* Is the new range completely covered? */
>> if (entry->addr < start && entry_end > end) {
>> e820__range_add(end, entry_end - end, entry->type);
>> + if (entry->crypto_capable)
>> + e820__range_mark_as_crypto(end, entry_end - end);
>> +
>
> Why introduce this new function call instead of adding an extra
> 'crypto_capable' argument to e820__range_add() ?
I thought about it, but I would like not to change the signature of
e820__range_add. Either way, here I could use __e820__range_add which
it does accept crypto_capable as an argument, just as I did in
e820__range_update.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-11-25 18:23 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-24 20:34 [PATCH v2 0/5] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 1/5] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 2/5] mm/mmzone: Tag pg_data_t " Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 3/5] x86/e820: Tag e820_entry " Martin Fernandez
2021-11-25 7:06 ` Dov Murik
2021-11-25 18:12 ` Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 4/5] x86/efi: Tag e820_entries as crypto capable from EFI memmap Martin Fernandez
2021-11-24 20:34 ` [PATCH v2 5/5] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).