All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption
@ 2022-04-25 17:15 Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, 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. fwupd's people have seen cases where it seems like there
is memory encryption because all the hardware is capable of doing it,
but on a closer look there is not, either because of system firmware
or because some component requires updating to enable the feature.

It's planned to make it part of a specification that can be passed to
people purchasing hardware

These checks will run at every boot. The specification is called Host
Security ID: https://fwupd.github.io/libfwupdplugin/hsi.html.

We choosed to do it a per-node basis because although an ABI that
shows that the whole system memory is capable of encryption would be
useful for the fwupd use case, doing it in a per-node basis gives also
the capability to the user to target allocations from applications to
NUMA nodes which have encryption capabilities.

I did some tests for some of the functions introduced (and modified)
in e820.c. Sadly KUnit is not able to test __init functions and data
so I had some warnings during the linking. There is a KUnit patch
already to fix that [1]. I wanted to wait for it to be merged but it
is taking more time than I expected so I'm sending this without tests
for now.

[1] https://lore.kernel.org/lkml/20220419040515.43693-1-brendanhiggins@google.com/T/


Changes since v6:

Fixes in __e820__handle_range_update

Const correctness in e820.c

Correct alignment in memblock.h

Rework memblock_overlaps_region


Changes since v5:

Refactor e820__range_{update, remove, set_crypto_capable} in order to
avoid code duplication.

Warn the user when a node has both encryptable and non-encryptable
regions.

Check that e820_table has enough size to store both current e820_table
and EFI memmap.


Changes since v4:

Add enum to represent the cryptographic capabilities in e820:
e820_crypto_capabilities.

Revert __e820__range_update, only adding the new argument for
__e820__range_add about crypto capabilities.

Add a function __e820__range_update_crypto similar to
__e820__range_update but to only update this new field.


Changes since v3:

Update date in Doc/ABI file.

More information about the fwupd usecase and the rationale behind
doing it in a per-NUMA-node.


Changes since v2:

e820__range_mark_crypto -> e820__range_mark_crypto_capable.

In e820__range_remove: Create a region with crypto capabilities
instead of creating one without it and then mark it.


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 (8):
  mm/memblock: Tag memblocks with crypto capabilities
  mm/mmzone: Tag pg_data_t with crypto capabilities
  x86/e820: Add infrastructure to refactor e820__range_{update,remove}
  x86/e820: Refactor __e820__range_update
  x86/e820: Refactor e820__range_remove
  x86/e820: Tag e820_entry with crypto capabilities
  x86/efi: Mark 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            |  12 +-
 arch/x86/kernel/e820.c                       | 481 +++++++++++++++----
 arch/x86/platform/efi/efi.c                  |  37 ++
 drivers/base/node.c                          |  10 +
 include/linux/memblock.h                     |   5 +
 include/linux/mmzone.h                       |   3 +
 mm/memblock.c                                |  62 +++
 mm/page_alloc.c                              |   1 +
 10 files changed, 524 insertions(+), 98 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-devices-node

-- 
2.30.2


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-26  6:10   ` Mike Rapoport
  2022-04-25 17:15 ` [PATCH v7 2/8] mm/mmzone: Tag pg_data_t " Martin Fernandez
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, 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. Warn the user if a node has both encryptable and
non-encryptable regions.

Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
 include/linux/memblock.h |  5 ++++
 mm/memblock.c            | 62 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 50ad19662a32..00c4f1a20335 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -40,6 +40,7 @@ extern unsigned long long max_possible_pfn;
  * via a driver, and never indicated in the firmware-provided memory map as
  * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in the
  * kernel resource tree.
+ * @MEMBLOCK_CRYPTO_CAPABLE: capable of hardware encryption
  */
 enum memblock_flags {
 	MEMBLOCK_NONE		= 0x0,	/* No special request */
@@ -47,6 +48,7 @@ enum memblock_flags {
 	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
 	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
 	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
+	MEMBLOCK_CRYPTO_CAPABLE = 0x10,	/* capable of hardware encryption */
 };
 
 /**
@@ -120,6 +122,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 e4f03a6e8e56..fe62f81572e6 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -191,6 +191,40 @@ 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.
+ *
+ * Return:
+ * true if every region in memory memblock_type is capable of
+ * encryption, false otherwise.
+ */
+bool __init_memblock memblock_node_is_crypto_capable(int nid)
+{
+	struct memblock_region *region;
+	int crypto_capables = 0;
+	int not_crypto_capables = 0;
+
+	for_each_mem_region(region) {
+		if (memblock_get_region_node(region) == nid) {
+			if (region->flags & MEMBLOCK_CRYPTO_CAPABLE)
+				crypto_capables++;
+			else
+				not_crypto_capables++;
+		}
+	}
+
+	if (crypto_capables > 0 && not_crypto_capables > 0)
+		pr_warn("Node %d has %d regions that are encryptable and %d regions that aren't",
+			nid, not_crypto_capables, crypto_capables);
+
+	return not_crypto_capables == 0;
+}
+
 /**
  * __memblock_find_range_bottom_up - find free area utility in bottom-up
  * @start: start of candidate range
@@ -891,6 +925,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] 20+ messages in thread

* [PATCH v7 2/8] mm/mmzone: Tag pg_data_t with crypto capabilities
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-26  6:16   ` Mike Rapoport
  2022-04-25 17:15 ` [PATCH v7 3/8] x86/e820: Add infrastructure to refactor e820__range_{update,remove} Martin Fernandez
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, Martin Fernandez

Add a new member in the pg_data_t struct to 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 46ffab808f03..89054af9e599 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -886,6 +886,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 0e42038382c1..a244151045b4 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7699,6 +7699,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);
 
 	if (start_pfn != end_pfn) {
 		pr_info("Initmem setup node %d [mem %#018Lx-%#018Lx]\n", nid,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v7 3/8] x86/e820: Add infrastructure to refactor e820__range_{update,remove}
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 2/8] mm/mmzone: Tag pg_data_t " Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 4/8] x86/e820: Refactor __e820__range_update Martin Fernandez
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, Martin Fernandez

__e820__range_update and e820__range_remove had a very similar flow in
its implementation with a few lines different from each other, the
lines that actually perform the modification over the e820_table. The
similiraties were found in the checks for the different cases on how
each entry intersects with the given range (if it does at all). These
checks were very presice and error prone so it was not a good idea to
have them in both places.

Since I need to add a third one, similar to this two, in this and the
following patches I'll propose a refactor of these functions.

In this patch I introduce:

- A new type e820_entry_updater that will carry three callbacks, those
callbacks will decide WHEN to perform actions over the e820_table and
WHAY actions are going to be performed.

  Note that there is a void pointer "data". This pointer will carry
  useful information for the callbacks, like the type that we want to
  update in e820__range_update or if we want to check the type in
  e820__range_remove. Check it out in the next patches where I do the
  rework of __e820__range_update and e820__range_remove.

- A new function __e820__handle_range_update that has the flow of the
original two functions to refactor. Together with e820_entry_updater
will perform the desired update on the input table.


On version 6 of this patch some people pointed out that this solution
was over-complicated. Mike Rapoport suggested a another solution [1].

I took a look at that, and although it is indeed simpler it's more
confusing at the same time. I think is manageable to have a single
function to update or remove sections of the table (what Mike did),
but when I added the functionality to also update the crypto_capable
it became really hard to manage.

I think that the approach presented in this patch it's complex but is
easier to read, to extend and to test.

[1] https://git.kernel.org/rppt/h/x86/e820-update-range

Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
 arch/x86/kernel/e820.c | 148 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)

diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index f267205f2d5a..923585ab8377 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -459,6 +459,154 @@ static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entr
 	return __append_e820_table(entries, nr_entries);
 }
 
+/**
+ * struct e820_entry_updater - Helper type for
+ * __e820__handle_range_update().
+ * @should_update: Return true if @entry needs to be updated, false
+ * otherwise.
+ * @update: Apply desired actions to an @entry that is inside the
+ * range and satisfies @should_update.
+ * @new: Create new entry in the table with information gathered from
+ * @original and @data.
+ *
+ * Each function corresponds to an action that
+ * __e820__handle_range_update() does. Callbacks need to cast @data back
+ * to the corresponding type.
+ */
+struct e820_entry_updater {
+	bool (*should_update)(const struct e820_entry *entry, const void *data);
+	void (*update)(struct e820_entry *entry, const void *data);
+	void (*new)(struct e820_table *table, u64 new_start, u64 new_size,
+		    const struct e820_entry *original, const void *data);
+};
+
+/**
+ * __e820__handle_intersected_range_update() - Helper function for
+ * __e820__handle_range_update().
+ * @table: Target e820_table.
+ * @start: Start of the range.
+ * @size: Size of the range.
+ * @entry: Current entry that __e820__handle_range_update() was
+ * looking into.
+ * @updater: updater parameter of __e820__handle_range_update().
+ * @data: data parameter of __e820__handle_range_update().
+ *
+ * Helper for __e820__handle_range_update to handle the case where
+ * neither the entry completely covers the range nor the range
+ * completely covers the entry.
+ *
+ * Return: The updated size.
+ */
+static u64 __init
+__e820__handle_intersected_range_update(struct e820_table *table,
+					u64 start,
+					u64 size,
+					struct e820_entry *entry,
+					const struct e820_entry_updater *updater,
+					const void *data)
+{
+	u64 end;
+	u64 entry_end = entry->addr + entry->size;
+	u64 inner_start;
+	u64 inner_end;
+	u64 updated_size = 0;
+
+	if (size > (ULLONG_MAX - start))
+		size = ULLONG_MAX - start;
+
+	end = start + size;
+	inner_start = max(start, entry->addr);
+	inner_end = min(end, entry_end);
+
+	/* Range and entry do intersect and... */
+	if (inner_start < inner_end) {
+		/* Entry is on the left */
+		if (entry->addr < inner_start) {
+			/* Resize current entry */
+			entry->size = inner_start - entry->addr;
+		/* Entry is on the right */
+		} else {
+			/* Resize and move current section */
+			entry->addr = inner_end;
+			entry->size = entry_end - inner_end;
+		}
+		/* Create new entry with intersected region */
+		updater->new(table, inner_start, inner_end - inner_start, entry, data);
+
+		updated_size += inner_end - inner_start;
+	} /* Else: [start, end) doesn't cover entry */
+
+	return updated_size;
+}
+
+/**
+ * __e820__handle_range_update(): Helper function to update an address
+ * range in a e820_table
+ * @table: e820_table that we want to modify.
+ * @start: Start of the range.
+ * @size: Size of the range.
+ * @updater: Callbacks to modify the table.
+ * @data: Information to modify the table. This must be an struct
+ * e820_type_*_data.
+ *
+ * Update the table @table in [@start, @start + @size) doing the
+ * actions given in @updater.
+ *
+ * Return: The updated size.
+ */
+static u64 __init
+__e820__handle_range_update(struct e820_table *table,
+			    u64 start,
+			    u64 size,
+			    const struct e820_entry_updater *updater,
+			    const void *data)
+{
+	u64 updated_size = 0;
+	u64 end;
+	unsigned int i;
+
+	if (size > (ULLONG_MAX - start))
+		size = ULLONG_MAX - start;
+
+	end = start + size;
+
+	for (i = 0; i < table->nr_entries; i++) {
+		struct e820_entry *entry = &table->entries[i];
+		u64 entry_end = entry->addr + entry->size;
+
+		if (updater->should_update(entry, data)) {
+			/* Range completely covers entry */
+			if (entry->addr >= start && entry_end <= end) {
+				updated_size += entry->size;
+				updater->update(entry, data);
+			/* Entry completely covers range */
+			} else if (start > entry->addr && end < entry_end) {
+				/* Resize current entry */
+				entry->size = start - entry->addr;
+
+				/* Create new entry with intersection region */
+				updater->new(table, start, size, entry, data);
+
+				/*
+				 * Create a new entry for the leftover
+				 * of the current entry
+				 */
+				__e820__range_add(table, end, entry_end - end,
+						  entry->type,
+						  entry->crypto_capable);
+
+				updated_size += size;
+			} else {
+				updated_size +=
+					__e820__handle_intersected_range_update(table, start, size,
+										entry, updater, data);
+			}
+		}
+	}
+
+	return updated_size;
+}
+
 static u64 __init
 __e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
 {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v7 4/8] x86/e820: Refactor __e820__range_update
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
                   ` (2 preceding siblings ...)
  2022-04-25 17:15 ` [PATCH v7 3/8] x86/e820: Add infrastructure to refactor e820__range_{update,remove} Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 5/8] x86/e820: Refactor e820__range_remove Martin Fernandez
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, Martin Fernandez

Refactor __e820__range_update with the introduction of
e820_type_updater_data, indented to be used as the void pointer in the
e820_entry_updater callbacks, and the implementation of the callbacks
to perform the update of the type in a range of a e820_table.

Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
 arch/x86/kernel/e820.c | 146 +++++++++++++++++++++++++----------------
 1 file changed, 89 insertions(+), 57 deletions(-)

diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 923585ab8377..763b8b20a1fd 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -607,80 +607,112 @@ __e820__handle_range_update(struct e820_table *table,
 	return updated_size;
 }
 
-static u64 __init
-__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
-{
-	u64 end;
-	unsigned int i;
-	u64 real_updated_size = 0;
-
-	BUG_ON(old_type == new_type);
-
-	if (size > (ULLONG_MAX - start))
-		size = ULLONG_MAX - start;
+/**
+ * struct e820_type_updater_data - Helper type for
+ * __e820__range_update().
+ * @old_type: old_type parameter of __e820__range_update().
+ * @new_type: new_type parameter of __e820__range_update().
+ *
+ * This is intended to be used as the @data argument for the
+ * e820_entry_updater callbacks.
+ */
+struct e820_type_updater_data {
+	enum e820_type old_type;
+	enum e820_type new_type;
+};
 
-	end = start + size;
-	printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", start, end - 1);
-	e820_print_type(old_type);
-	pr_cont(" ==> ");
-	e820_print_type(new_type);
-	pr_cont("\n");
+static bool __init type_updater__should_update(const struct e820_entry *entry,
+					       const void *data)
+{
+	const struct e820_type_updater_data *type_updater_data =
+		(const struct e820_type_updater_data *)data;
 
-	for (i = 0; i < table->nr_entries; i++) {
-		struct e820_entry *entry = &table->entries[i];
-		u64 final_start, final_end;
-		u64 entry_end;
+	return entry->type == type_updater_data->old_type;
+}
 
-		if (entry->type != old_type)
-			continue;
+static void __init type_updater__update(struct e820_entry *entry,
+					const void *data)
+{
+	const struct e820_type_updater_data *type_updater_data =
+		(const struct e820_type_updater_data *)data;
 
-		entry_end = entry->addr + entry->size;
+	entry->type = type_updater_data->new_type;
+}
 
-		/* Completely covered by new range? */
-		if (entry->addr >= start && entry_end <= end) {
-			entry->type = new_type;
-			real_updated_size += entry->size;
-			continue;
-		}
+static void __init type_updater__new(struct e820_table *table, u64 new_start,
+				     u64 new_size,
+				     const struct e820_entry *original,
+				     const void *data)
+{
+	const struct e820_type_updater_data *type_updater_data =
+		(const struct e820_type_updater_data *)data;
 
-		/* 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);
-			entry->size = start - entry->addr;
-			real_updated_size += size;
-			continue;
-		}
+	__e820__range_add(table, new_start, new_size,
+			  type_updater_data->new_type, original->crypto_capable);
+}
 
-		/* Partially covered: */
-		final_start = max(start, entry->addr);
-		final_end = min(end, entry_end);
-		if (final_start >= final_end)
-			continue;
+static u64 __init __e820__range_update(struct e820_table *table, u64 start,
+				       u64 size, enum e820_type old_type,
+				       enum e820_type new_type)
+{
+	struct e820_entry_updater updater = {
+		.should_update = type_updater__should_update,
+		.update = type_updater__update,
+		.new = type_updater__new
+	};
 
-		__e820__range_add(table, final_start, final_end - final_start, new_type);
+	struct e820_type_updater_data data = {
+		.old_type = old_type,
+		.new_type = new_type
+	};
 
-		real_updated_size += final_end - final_start;
+	BUG_ON(old_type == new_type);
 
-		/*
-		 * Left range could be head or tail, so need to update
-		 * its size first:
-		 */
-		entry->size -= final_end - final_start;
-		if (entry->addr < final_start)
-			continue;
+	printk(KERN_DEBUG "e820: update [mem %#018Lx-%#018Lx] ", start,
+	       start + size - 1);
+	e820_print_type(old_type);
+	pr_cont(" ==> ");
+	e820_print_type(new_type);
+	pr_cont("\n");
 
-		entry->addr = final_end;
-	}
-	return real_updated_size;
+	return __e820__handle_range_update(table, start, size, &updater, &data);
 }
 
-u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
+/**
+ * e820__range_update() - Update the type of a given address range in
+ * e820_table.
+ * @start: Start of the range.
+ * @size: Size of the range.
+ * @old_type: Type that we want to change.
+ * @new_type: New type to replace @old_type.
+ *
+ * Update type of addresses in [@start, @start + @size) from @old_type
+ * to @new_type in e820_table.
+ *
+ * Return: The size updated.
+ */
+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);
 }
 
-static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type  new_type)
+/**
+ * e820__range_update_kexec() - Update the type of a given address
+ * range in e820_table_kexec.
+ * @start: Start of the range.
+ * @size: Size of the range.
+ * @old_type: Type that we want to change.
+ * @new_type: New type to replace @old_type.
+ *
+ * Update type of addresses in [@start, @start + @size) from @old_type
+ * to @new_type in e820_table_kexec.
+ *
+ * Return: The size updated.
+ */
+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);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v7 5/8] x86/e820: Refactor e820__range_remove
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
                   ` (3 preceding siblings ...)
  2022-04-25 17:15 ` [PATCH v7 4/8] x86/e820: Refactor __e820__range_update Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-26 15:10   ` Dave Hansen
  2022-04-25 17:15 ` [PATCH v7 6/8] x86/e820: Tag e820_entry with crypto capabilities Martin Fernandez
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, Martin Fernandez

Refactor e820__range_remove with the introduction of
e820_remover_data, indented to be used as the void pointer in the
e820_entry_updater callbacks, and the implementation of the callbacks
remove a range in the e820_table.

Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
 arch/x86/kernel/e820.c | 112 ++++++++++++++++++++++-------------------
 1 file changed, 60 insertions(+), 52 deletions(-)

diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 763b8b20a1fd..9e32c9819e99 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -717,66 +717,74 @@ static u64 __init e820__range_update_kexec(u64 start, u64 size,
 	return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
 }
 
-/* Remove a range of memory from the E820 table: */
-u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type)
-{
-	int i;
-	u64 end;
-	u64 real_removed_size = 0;
-
-	if (size > (ULLONG_MAX - start))
-		size = ULLONG_MAX - start;
-
-	end = start + size;
-	printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", start, end - 1);
-	if (check_type)
-		e820_print_type(old_type);
-	pr_cont("\n");
-
-	for (i = 0; i < e820_table->nr_entries; i++) {
-		struct e820_entry *entry = &e820_table->entries[i];
-		u64 final_start, final_end;
-		u64 entry_end;
+/**
+ * struct e820_remover_data - Helper type for e820__range_remove().
+ * @old_type: old_type parameter of e820__range_remove().
+ * @check_type: check_type parameter of e820__range_remove().
+ *
+ * This is intended to be used as the @data argument for the
+ * e820_entry_updater callbacks.
+ */
+struct e820_remover_data {
+	enum e820_type old_type;
+	bool check_type;
+};
 
-		if (check_type && entry->type != old_type)
-			continue;
+static bool __init remover__should_update(const struct e820_entry *entry,
+					  const void *data)
+{
+	const struct e820_remover_data *remover_data =
+		(const struct e820_remover_data *)data;
 
-		entry_end = entry->addr + entry->size;
+	return !remover_data->check_type ||
+	       entry->type == remover_data->old_type;
+}
 
-		/* Completely covered? */
-		if (entry->addr >= start && entry_end <= end) {
-			real_removed_size += entry->size;
-			memset(entry, 0, sizeof(*entry));
-			continue;
-		}
+static void __init remover__update(struct e820_entry *entry, const void *data)
+{
+	memset(entry, 0, sizeof(*entry));
+}
 
-		/* Is the new range completely covered? */
-		if (entry->addr < start && entry_end > end) {
-			e820__range_add(end, entry_end - end, entry->type);
-			entry->size = start - entry->addr;
-			real_removed_size += size;
-			continue;
-		}
+static void __init remover__new(struct e820_table *table, u64 new_start,
+				u64 new_size, const struct e820_entry *original,
+				const void *data)
+{
+}
 
-		/* Partially covered: */
-		final_start = max(start, entry->addr);
-		final_end = min(end, entry_end);
-		if (final_start >= final_end)
-			continue;
+/**
+ * e820__range_remove() - Remove an address range from e820_table.
+ * @start: Start of the address range.
+ * @size: Size of the address range.
+ * @old_type: Type of the entries that we want to remove.
+ * @check_type: Bool to decide if ignore @old_type or not.
+ *
+ * Remove [@start, @start + @size) from e820_table. If @check_type is
+ * true remove only entries with type @old_type.
+ *
+ * Return: The size removed.
+ */
+u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type,
+			      bool check_type)
+{
+	struct e820_entry_updater updater = {
+		.should_update = remover__should_update,
+		.update = remover__update,
+		.new = remover__new
+	};
 
-		real_removed_size += final_end - final_start;
+	struct e820_remover_data data = {
+		.check_type = check_type,
+		.old_type = old_type
+	};
 
-		/*
-		 * Left range could be head or tail, so need to update
-		 * the size first:
-		 */
-		entry->size -= final_end - final_start;
-		if (entry->addr < final_start)
-			continue;
+	printk(KERN_DEBUG "e820: remove [mem %#018Lx-%#018Lx] ", start,
+	       start + size - 1);
+	if (check_type)
+		e820_print_type(old_type);
+	pr_cont("\n");
 
-		entry->addr = final_end;
-	}
-	return real_removed_size;
+	return __e820__handle_range_update(e820_table, start, size, &updater,
+					    &data);
 }
 
 void __init e820__update_table_print(void)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v7 6/8] x86/e820: Tag e820_entry with crypto capabilities
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
                   ` (4 preceding siblings ...)
  2022-04-25 17:15 ` [PATCH v7 5/8] x86/e820: Refactor e820__range_remove Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 7/8] x86/efi: Mark e820_entries as crypto capable from EFI memmap Martin Fernandez
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, Martin Fernandez

Add a new enum for crypto capabilities. I choosed an enum instead of a
boolean for more visibility in the code and because maybe in the
future we would like to track from where the cryptographic
capabilities comes (in this case, the EFI memmap).

Add a new member in e820_entry to hold this new enum.

Add a new function e820__range_set_crypto_capable to mark all the
entries in a range of addresses as encryptable. This will be called
when initializing EFI.

Change e820__update_table to handle merging and overlap problems
taking into account crypto_capable.

Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
 arch/x86/include/asm/e820/api.h   |   1 +
 arch/x86/include/asm/e820/types.h |  12 +++-
 arch/x86/kernel/e820.c            | 109 +++++++++++++++++++++++++++++-
 3 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h
index e8f58ddd06d9..4b3b01fafdd1 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_set_crypto_capable(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..aef03c665f5e 100644
--- a/arch/x86/include/asm/e820/types.h
+++ b/arch/x86/include/asm/e820/types.h
@@ -46,6 +46,11 @@ enum e820_type {
 	E820_TYPE_RESERVED_KERN	= 128,
 };
 
+enum e820_crypto_capabilities {
+	E820_NOT_CRYPTO_CAPABLE	= 0,
+	E820_CRYPTO_CAPABLE	= 1,
+};
+
 /*
  * A single E820 map entry, describing a memory range of [addr...addr+size-1],
  * of 'type' memory type:
@@ -53,9 +58,10 @@ enum e820_type {
  * (We pack it because there can be thousands of them on large systems.)
  */
 struct e820_entry {
-	u64			addr;
-	u64			size;
-	enum e820_type		type;
+	u64				addr;
+	u64				size;
+	enum e820_type			type;
+	enum e820_crypto_capabilities	crypto_capable;
 } __attribute__((packed));
 
 /*
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 9e32c9819e99..5837b7c1d197 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -163,7 +163,9 @@ 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,
+				     enum e820_crypto_capabilities crypto_capable)
 {
 	int x = table->nr_entries;
 
@@ -176,12 +178,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, E820_NOT_CRYPTO_CAPABLE);
 }
 
 static void __init e820_print_type(enum e820_type type)
@@ -211,6 +214,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 == E820_CRYPTO_CAPABLE)
+			pr_cont("; crypto-capable");
 		pr_cont("\n");
 	}
 }
@@ -327,6 +332,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;
+	enum e820_crypto_capabilities current_crypto, last_crypto;
 
 	/* If there's only one memory region, don't bother: */
 	if (table->nr_entries < 2)
@@ -367,6 +373,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 = E820_NOT_CRYPTO_CAPABLE;
 
 	/* Loop through change-points, determining effect on the new map: */
 	for (chg_idx = 0; chg_idx < chg_nr; chg_idx++) {
@@ -388,13 +395,19 @@ int __init e820__update_table(struct e820_table *table)
 		 * 1=usable, 2,3,4,4+=unusable)
 		 */
 		current_type = 0;
+		current_crypto = E820_CRYPTO_CAPABLE;
 		for (i = 0; i < overlap_entries; i++) {
+			if (overlap_list[i]->crypto_capable < 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 +419,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;
 		}
 	}
 
@@ -787,6 +803,91 @@ u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type,
 					    &data);
 }
 
+/**
+ * struct e820_crypto_updater_data - Helper type for
+ * __e820__range_update_crypto().
+ * @crypto_capable: crypto_capable parameter of
+ * __e820__range_update_crypto().
+ *
+ * This is intended to be used as the @data argument for the
+ * e820_entry_updater callbacks.
+ */
+struct e820_crypto_updater_data {
+	enum e820_crypto_capabilities crypto_capable;
+};
+
+static bool __init crypto_updater__should_update(const struct e820_entry *entry,
+						 const void *data)
+{
+	const struct e820_crypto_updater_data *crypto_updater_data =
+		(const struct e820_crypto_updater_data *)data;
+
+	return crypto_updater_data->crypto_capable != entry->crypto_capable;
+}
+
+static void __init crypto_updater__update(struct e820_entry *entry,
+					  const void *data)
+{
+	const struct e820_crypto_updater_data *crypto_updater_data =
+		(const struct e820_crypto_updater_data *)data;
+
+	entry->crypto_capable = crypto_updater_data->crypto_capable;
+}
+
+static void __init crypto_updater__new(struct e820_table *table, u64 new_start,
+				       u64 new_size,
+				       const struct e820_entry *original,
+				       const void *data)
+{
+	const struct e820_crypto_updater_data *crypto_updater_data =
+		(const struct e820_crypto_updater_data *)data;
+
+	__e820__range_add(table, new_start, new_size, original->type,
+			  crypto_updater_data->crypto_capable);
+}
+
+static u64 __init
+__e820__range_update_crypto(struct e820_table *table, u64 start, u64 size,
+			    enum e820_crypto_capabilities crypto_capable)
+{
+	struct e820_entry_updater updater = {
+		.should_update = crypto_updater__should_update,
+		.update = crypto_updater__update,
+		.new = crypto_updater__new
+	};
+
+	struct e820_crypto_updater_data data = {
+		.crypto_capable = crypto_capable,
+	};
+
+	printk(KERN_DEBUG "e820: crypto update [mem %#018Lx-%#018Lx]", start,
+	       start + size - 1);
+	pr_cont(" ==> ");
+	if (crypto_capable == E820_CRYPTO_CAPABLE)
+		pr_cont("crypto capable");
+	else
+		pr_cont("not crypto capable");
+	pr_cont("\n");
+
+	return __e820__handle_range_update(table, start, size, &updater, &data);
+}
+
+/**
+ * e820__range_set_crypto_capable() - Set %E820_CRYPTO_CAPABLE to a
+ * given range of addresses in e820_table.
+ * @start: Start of the range.
+ * @size: Size of the range.
+ *
+ * Set %E820_CRYPTO_CAPABLE to [@start, @start + @size) in e820_table.
+ *
+ * Return: The size updated.
+ */
+u64 __init e820__range_set_crypto_capable(u64 start, u64 size)
+{
+	return __e820__range_update_crypto(e820_table, start, size,
+					   E820_CRYPTO_CAPABLE);
+}
+
 void __init e820__update_table_print(void)
 {
 	if (e820__update_table(e820_table))
@@ -1529,6 +1630,8 @@ void __init e820__memblock_setup(void)
 			continue;
 
 		memblock_add(entry->addr, entry->size);
+		if (entry->crypto_capable == E820_CRYPTO_CAPABLE)
+			memblock_mark_crypto_capable(entry->addr, entry->size);
 	}
 
 	/* Throw away partial pages: */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v7 7/8] x86/efi: Mark e820_entries as crypto capable from EFI memmap
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
                   ` (5 preceding siblings ...)
  2022-04-25 17:15 ` [PATCH v7 6/8] x86/e820: Tag e820_entry with crypto capabilities Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-25 17:15 ` [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
  2022-04-25 17:23 ` [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Andrew Morton
  8 siblings, 0 replies; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, 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.

If add_efi_memmap is false, also check that the e820_table has enough
size to (possibly) store also the EFI memmap.

Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
---
 arch/x86/platform/efi/efi.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 147c30a81f15..3efa1c620c75 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_set_crypto_capable(start, size);
 	}
 	e820__update_table(e820_table);
 }
@@ -441,6 +443,34 @@ 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;
+
+	/*
+	 * Calling e820__range_set_crypto_capable several times
+	 * creates a bunch of entries in the E820 table. They probably
+	 * will get merged when calling update_table but we need the
+	 * space there anyway
+	 */
+	if (efi.memmap.nr_map + e820_table->nr_entries >= E820_MAX_ENTRIES) {
+		pr_err_once("E820 table is not large enough to fit EFI memmap; not marking entries as crypto capable\n");
+		return;
+	}
+
+	for_each_efi_memory_desc(md) {
+		if (md->attribute & EFI_MEMORY_CPU_CRYPTO)
+			e820__range_set_crypto_capable(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 +524,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] 20+ messages in thread

* [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
                   ` (6 preceding siblings ...)
  2022-04-25 17:15 ` [PATCH v7 7/8] x86/efi: Mark e820_entries as crypto capable from EFI memmap Martin Fernandez
@ 2022-04-25 17:15 ` Martin Fernandez
  2022-04-26  6:16   ` Mike Rapoport
  2022-04-25 17:23 ` [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Andrew Morton
  8 siblings, 1 reply; 20+ messages in thread
From: Martin Fernandez @ 2022-04-25 17:15 UTC (permalink / raw)
  To: linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook, 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..5fd5dc7fc2eb
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-node
@@ -0,0 +1,10 @@
+What:		/sys/devices/system/node/nodeX/crypto_capable
+Date:		April 2022
+Contact:	Martin Fernandez <martin.fernandez@eclypsium.com>
+Users:		fwupd (https://fwupd.org)
+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 ec8bb24a5a22..1df15ea03c27 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] 20+ messages in thread

* Re: [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption
  2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
                   ` (7 preceding siblings ...)
  2022-04-25 17:15 ` [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
@ 2022-04-25 17:23 ` Andrew Morton
  8 siblings, 0 replies; 20+ messages in thread
From: Andrew Morton @ 2022-04-25 17:23 UTC (permalink / raw)
  To: Martin Fernandez
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, rppt, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On Mon, 25 Apr 2022 14:15:18 -0300 Martin Fernandez <martin.fernandez@eclypsium.com> wrote:

> Show for each node if every memory descriptor in that node has the
> EFI_MEMORY_CPU_CRYPTO attribute.

The MM patches look OK to me.  Mike, can you please opine?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities
  2022-04-25 17:15 ` [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
@ 2022-04-26  6:10   ` Mike Rapoport
  2022-04-26 12:59     ` Martin Fernandez
  0 siblings, 1 reply; 20+ messages in thread
From: Mike Rapoport @ 2022-04-26  6:10 UTC (permalink / raw)
  To: Martin Fernandez
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On Mon, Apr 25, 2022 at 02:15:19PM -0300, Martin Fernandez wrote:
> 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. Warn the user if a node has both encryptable and
> non-encryptable regions.
> 
> Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
> ---
>  include/linux/memblock.h |  5 ++++
>  mm/memblock.c            | 62 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 67 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 50ad19662a32..00c4f1a20335 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -40,6 +40,7 @@ extern unsigned long long max_possible_pfn;
>   * via a driver, and never indicated in the firmware-provided memory map as
>   * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in the
>   * kernel resource tree.
> + * @MEMBLOCK_CRYPTO_CAPABLE: capable of hardware encryption
>   */
>  enum memblock_flags {
>  	MEMBLOCK_NONE		= 0x0,	/* No special request */
> @@ -47,6 +48,7 @@ enum memblock_flags {
>  	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
>  	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>  	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
> +	MEMBLOCK_CRYPTO_CAPABLE = 0x10,	/* capable of hardware encryption */
>  };
>  
>  /**
> @@ -120,6 +122,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 e4f03a6e8e56..fe62f81572e6 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -191,6 +191,40 @@ 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.
> + *
> + * Return:
> + * true if every region in memory memblock_type is capable of

I'd s/in memory memblock_type/in @nid

> + * encryption, false otherwise.
> + */
> +bool __init_memblock memblock_node_is_crypto_capable(int nid)
> +{
> +	struct memblock_region *region;
> +	int crypto_capables = 0;
> +	int not_crypto_capables = 0;
> +
> +	for_each_mem_region(region) {
> +		if (memblock_get_region_node(region) == nid) {
> +			if (region->flags & MEMBLOCK_CRYPTO_CAPABLE)
> +				crypto_capables++;
> +			else
> +				not_crypto_capables++;
> +		}
> +	}
> +
> +	if (crypto_capables > 0 && not_crypto_capables > 0)
> +		pr_warn("Node %d has %d regions that are encryptable and %d regions that aren't",
> +			nid, not_crypto_capables, crypto_capables);
> +
> +	return not_crypto_capables == 0;

This will return true for memoryless nodes as well. Do you mean to consider
them as capable of encryption?

> +}
> +
>  /**
>   * __memblock_find_range_bottom_up - find free area utility in bottom-up
>   * @start: start of candidate range
> @@ -891,6 +925,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
> 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities
  2022-04-25 17:15 ` [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
@ 2022-04-26  6:16   ` Mike Rapoport
  2022-04-26 13:01     ` Martin Fernandez
  0 siblings, 1 reply; 20+ messages in thread
From: Mike Rapoport @ 2022-04-26  6:16 UTC (permalink / raw)
  To: Martin Fernandez
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On Mon, Apr 25, 2022 at 02:15:26PM -0300, Martin Fernandez wrote:
> 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..5fd5dc7fc2eb
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-devices-node
> @@ -0,0 +1,10 @@
> +What:		/sys/devices/system/node/nodeX/crypto_capable
> +Date:		April 2022
> +Contact:	Martin Fernandez <martin.fernandez@eclypsium.com>
> +Users:		fwupd (https://fwupd.org)
> +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.

I understand that currently this feature is only for x86, but if non-EFI
architectures will start using MEMBLOCK_CRYPTO_CAPABLE, the sysfs attribute
for will be relevant form them as well.

How about
	This value is 1 if all system memory in this node is capable of
	being protected with the CPU's memory cryptographic capabilities.
	It is 0 otherwise.
	On EFI systems the node will be marked with EFI_MEMORY_CPU_CRYPTO.

> \ No newline at end of file
> diff --git a/drivers/base/node.c b/drivers/base/node.c
> index ec8bb24a5a22..1df15ea03c27 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
> 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 2/8] mm/mmzone: Tag pg_data_t with crypto capabilities
  2022-04-25 17:15 ` [PATCH v7 2/8] mm/mmzone: Tag pg_data_t " Martin Fernandez
@ 2022-04-26  6:16   ` Mike Rapoport
  0 siblings, 0 replies; 20+ messages in thread
From: Mike Rapoport @ 2022-04-26  6:16 UTC (permalink / raw)
  To: Martin Fernandez
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On Mon, Apr 25, 2022 at 02:15:20PM -0300, Martin Fernandez wrote:
> Add a new member in the pg_data_t struct to 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>

Reviewed-by: Mike Rapoport <rppt@linux.ibm.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 46ffab808f03..89054af9e599 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -886,6 +886,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 0e42038382c1..a244151045b4 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -7699,6 +7699,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);
>  
>  	if (start_pfn != end_pfn) {
>  		pr_info("Initmem setup node %d [mem %#018Lx-%#018Lx]\n", nid,
> -- 
> 2.30.2
> 
> 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities
  2022-04-26  6:10   ` Mike Rapoport
@ 2022-04-26 12:59     ` Martin Fernandez
  2022-04-26 13:20       ` Mike Rapoport
  0 siblings, 1 reply; 20+ messages in thread
From: Martin Fernandez @ 2022-04-26 12:59 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On 4/26/22, Mike Rapoport <rppt@kernel.org> wrote:
> On Mon, Apr 25, 2022 at 02:15:19PM -0300, Martin Fernandez wrote:
>> 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. Warn the user if a node has both encryptable and
>> non-encryptable regions.
>>
>> Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
>> ---
>>  include/linux/memblock.h |  5 ++++
>>  mm/memblock.c            | 62 ++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 67 insertions(+)
>>
>> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
>> index 50ad19662a32..00c4f1a20335 100644
>> --- a/include/linux/memblock.h
>> +++ b/include/linux/memblock.h
>> @@ -40,6 +40,7 @@ extern unsigned long long max_possible_pfn;
>>   * via a driver, and never indicated in the firmware-provided memory map
>> as
>>   * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in
>> the
>>   * kernel resource tree.
>> + * @MEMBLOCK_CRYPTO_CAPABLE: capable of hardware encryption
>>   */
>>  enum memblock_flags {
>>  	MEMBLOCK_NONE		= 0x0,	/* No special request */
>> @@ -47,6 +48,7 @@ enum memblock_flags {
>>  	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
>>  	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>>  	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
>> +	MEMBLOCK_CRYPTO_CAPABLE = 0x10,	/* capable of hardware encryption */
>>  };
>>
>>  /**
>> @@ -120,6 +122,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 e4f03a6e8e56..fe62f81572e6 100644
>> --- a/mm/memblock.c
>> +++ b/mm/memblock.c
>> @@ -191,6 +191,40 @@ 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.
>> + *
>> + * Return:
>> + * true if every region in memory memblock_type is capable of
>
> I'd s/in memory memblock_type/in @nid
>

Good, thanks.

>> + * encryption, false otherwise.
>> + */
>> +bool __init_memblock memblock_node_is_crypto_capable(int nid)
>> +{
>> +	struct memblock_region *region;
>> +	int crypto_capables = 0;
>> +	int not_crypto_capables = 0;
>> +
>> +	for_each_mem_region(region) {
>> +		if (memblock_get_region_node(region) == nid) {
>> +			if (region->flags & MEMBLOCK_CRYPTO_CAPABLE)
>> +				crypto_capables++;
>> +			else
>> +				not_crypto_capables++;
>> +		}
>> +	}
>> +
>> +	if (crypto_capables > 0 && not_crypto_capables > 0)
>> +		pr_warn("Node %d has %d regions that are encryptable and %d regions
>> that aren't",
>> +			nid, not_crypto_capables, crypto_capables);
>> +
>> +	return not_crypto_capables == 0;
>
> This will return true for memoryless nodes as well. Do you mean to consider
> them as capable of encryption?
>

Not really, I didn't think about that to be honest. I don't think it's
a good idea to consider them as capable, right?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities
  2022-04-26  6:16   ` Mike Rapoport
@ 2022-04-26 13:01     ` Martin Fernandez
  0 siblings, 0 replies; 20+ messages in thread
From: Martin Fernandez @ 2022-04-26 13:01 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On 4/26/22, Mike Rapoport <rppt@kernel.org> wrote:
> On Mon, Apr 25, 2022 at 02:15:26PM -0300, Martin Fernandez wrote:
>> 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..5fd5dc7fc2eb
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-devices-node
>> @@ -0,0 +1,10 @@
>> +What:		/sys/devices/system/node/nodeX/crypto_capable
>> +Date:		April 2022
>> +Contact:	Martin Fernandez <martin.fernandez@eclypsium.com>
>> +Users:		fwupd (https://fwupd.org)
>> +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.
>
> I understand that currently this feature is only for x86, but if non-EFI
> architectures will start using MEMBLOCK_CRYPTO_CAPABLE, the sysfs attribute
> for will be relevant form them as well.
>
> How about
> 	This value is 1 if all system memory in this node is capable of
> 	being protected with the CPU's memory cryptographic capabilities.
> 	It is 0 otherwise.
> 	On EFI systems the node will be marked with EFI_MEMORY_CPU_CRYPTO.
>

Good point. I'll change it.

>> \ No newline at end of file
>> diff --git a/drivers/base/node.c b/drivers/base/node.c
>> index ec8bb24a5a22..1df15ea03c27 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
>>
>
> --
> Sincerely yours,
> Mike.
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities
  2022-04-26 12:59     ` Martin Fernandez
@ 2022-04-26 13:20       ` Mike Rapoport
  2022-04-26 13:25         ` Daniel Gutson
  0 siblings, 1 reply; 20+ messages in thread
From: Mike Rapoport @ 2022-04-26 13:20 UTC (permalink / raw)
  To: Martin Fernandez
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On Tue, Apr 26, 2022 at 09:59:04AM -0300, Martin Fernandez wrote:
> On 4/26/22, Mike Rapoport <rppt@kernel.org> wrote:
> > On Mon, Apr 25, 2022 at 02:15:19PM -0300, Martin Fernandez wrote:
> >> 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. Warn the user if a node has both encryptable and
> >> non-encryptable regions.
> >>
> >> Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
> >> ---
> >>  include/linux/memblock.h |  5 ++++
> >>  mm/memblock.c            | 62 ++++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 67 insertions(+)
> >>
> >> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> >> index 50ad19662a32..00c4f1a20335 100644
> >> --- a/include/linux/memblock.h
> >> +++ b/include/linux/memblock.h
> >> @@ -40,6 +40,7 @@ extern unsigned long long max_possible_pfn;
> >>   * via a driver, and never indicated in the firmware-provided memory map
> >> as
> >>   * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in
> >> the
> >>   * kernel resource tree.
> >> + * @MEMBLOCK_CRYPTO_CAPABLE: capable of hardware encryption
> >>   */
> >>  enum memblock_flags {
> >>  	MEMBLOCK_NONE		= 0x0,	/* No special request */
> >> @@ -47,6 +48,7 @@ enum memblock_flags {
> >>  	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
> >>  	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
> >>  	MEMBLOCK_DRIVER_MANAGED = 0x8,	/* always detected via a driver */
> >> +	MEMBLOCK_CRYPTO_CAPABLE = 0x10,	/* capable of hardware encryption */
> >>  };
> >>
> >>  /**
> >> @@ -120,6 +122,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 e4f03a6e8e56..fe62f81572e6 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -191,6 +191,40 @@ 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.
> >> + *
> >> + * Return:
> >> + * true if every region in memory memblock_type is capable of
> >
> > I'd s/in memory memblock_type/in @nid
> >
> 
> Good, thanks.
> 
> >> + * encryption, false otherwise.
> >> + */
> >> +bool __init_memblock memblock_node_is_crypto_capable(int nid)
> >> +{
> >> +	struct memblock_region *region;
> >> +	int crypto_capables = 0;
> >> +	int not_crypto_capables = 0;
> >> +
> >> +	for_each_mem_region(region) {
> >> +		if (memblock_get_region_node(region) == nid) {
> >> +			if (region->flags & MEMBLOCK_CRYPTO_CAPABLE)
> >> +				crypto_capables++;
> >> +			else
> >> +				not_crypto_capables++;
> >> +		}
> >> +	}
> >> +
> >> +	if (crypto_capables > 0 && not_crypto_capables > 0)
> >> +		pr_warn("Node %d has %d regions that are encryptable and %d regions
> >> that aren't",
> >> +			nid, not_crypto_capables, crypto_capables);
> >> +
> >> +	return not_crypto_capables == 0;
> >
> > This will return true for memoryless nodes as well. Do you mean to consider
> > them as capable of encryption?
> >
> 
> Not really, I didn't think about that to be honest. I don't think it's
> a good idea to consider them as capable, right?

I think capable of encryption would mean

	crypto_capables && !not_crypto_capables 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities
  2022-04-26 13:20       ` Mike Rapoport
@ 2022-04-26 13:25         ` Daniel Gutson
  0 siblings, 0 replies; 20+ messages in thread
From: Daniel Gutson @ 2022-04-26 13:25 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Martin Fernandez, linux-kernel, linux-efi, platform-driver-x86,
	linux-mm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, ardb, dvhart, andy,
	Greg Kroah-Hartman, rafael, akpm, Richard Hughes, Alex Bazhaniuk,
	Alison Schofield, Kees Cook

On Tue, Apr 26, 2022 at 10:21 AM Mike Rapoport <rppt@kernel.org> wrote:
>
> On Tue, Apr 26, 2022 at 09:59:04AM -0300, Martin Fernandez wrote:
> > On 4/26/22, Mike Rapoport <rppt@kernel.org> wrote:
> > > On Mon, Apr 25, 2022 at 02:15:19PM -0300, Martin Fernandez wrote:
> > >> 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. Warn the user if a node has both encryptable and
> > >> non-encryptable regions.
> > >>
> > >> Signed-off-by: Martin Fernandez <martin.fernandez@eclypsium.com>
> > >> ---
> > >>  include/linux/memblock.h |  5 ++++
> > >>  mm/memblock.c            | 62 ++++++++++++++++++++++++++++++++++++++++
> > >>  2 files changed, 67 insertions(+)
> > >>
> > >> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > >> index 50ad19662a32..00c4f1a20335 100644
> > >> --- a/include/linux/memblock.h
> > >> +++ b/include/linux/memblock.h
> > >> @@ -40,6 +40,7 @@ extern unsigned long long max_possible_pfn;
> > >>   * via a driver, and never indicated in the firmware-provided memory map
> > >> as
> > >>   * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in
> > >> the
> > >>   * kernel resource tree.
> > >> + * @MEMBLOCK_CRYPTO_CAPABLE: capable of hardware encryption
> > >>   */
> > >>  enum memblock_flags {
> > >>    MEMBLOCK_NONE           = 0x0,  /* No special request */
> > >> @@ -47,6 +48,7 @@ enum memblock_flags {
> > >>    MEMBLOCK_MIRROR         = 0x2,  /* mirrored region */
> > >>    MEMBLOCK_NOMAP          = 0x4,  /* don't add to kernel direct mapping */
> > >>    MEMBLOCK_DRIVER_MANAGED = 0x8,  /* always detected via a driver */
> > >> +  MEMBLOCK_CRYPTO_CAPABLE = 0x10, /* capable of hardware encryption */
> > >>  };
> > >>
> > >>  /**
> > >> @@ -120,6 +122,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 e4f03a6e8e56..fe62f81572e6 100644
> > >> --- a/mm/memblock.c
> > >> +++ b/mm/memblock.c
> > >> @@ -191,6 +191,40 @@ 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.
> > >> + *
> > >> + * Return:
> > >> + * true if every region in memory memblock_type is capable of
> > >
> > > I'd s/in memory memblock_type/in @nid
> > >
> >
> > Good, thanks.
> >
> > >> + * encryption, false otherwise.
> > >> + */
> > >> +bool __init_memblock memblock_node_is_crypto_capable(int nid)
> > >> +{
> > >> +  struct memblock_region *region;
> > >> +  int crypto_capables = 0;
> > >> +  int not_crypto_capables = 0;
> > >> +
> > >> +  for_each_mem_region(region) {
> > >> +          if (memblock_get_region_node(region) == nid) {
> > >> +                  if (region->flags & MEMBLOCK_CRYPTO_CAPABLE)
> > >> +                          crypto_capables++;
> > >> +                  else
> > >> +                          not_crypto_capables++;
> > >> +          }
> > >> +  }
> > >> +
> > >> +  if (crypto_capables > 0 && not_crypto_capables > 0)
> > >> +          pr_warn("Node %d has %d regions that are encryptable and %d regions
> > >> that aren't",
> > >> +                  nid, not_crypto_capables, crypto_capables);
> > >> +
> > >> +  return not_crypto_capables == 0;
> > >
> > > This will return true for memoryless nodes as well. Do you mean to consider
> > > them as capable of encryption?
> > >
> >
> > Not really, I didn't think about that to be honest. I don't think it's
> > a good idea to consider them as capable, right?
>
> I think capable of encryption would mean
>
>         crypto_capables && !not_crypto_capables

Since these operands were evaluated above with comparison ops, I would say
    crypto_capables > 0 && not_crypto_capables == 0
to improve readability and be explicit that they are numbers rather
than booleans.


>
> --
> Sincerely yours,
> Mike.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 5/8] x86/e820: Refactor e820__range_remove
  2022-04-25 17:15 ` [PATCH v7 5/8] x86/e820: Refactor e820__range_remove Martin Fernandez
@ 2022-04-26 15:10   ` Dave Hansen
  2022-04-26 17:37     ` Martin Fernandez
  0 siblings, 1 reply; 20+ messages in thread
From: Dave Hansen @ 2022-04-26 15:10 UTC (permalink / raw)
  To: Martin Fernandez, linux-kernel, linux-efi, platform-driver-x86, linux-mm
  Cc: tglx, mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy,
	gregkh, rafael, rppt, akpm, daniel.gutson, hughsient,
	alex.bazhaniuk, alison.schofield, keescook

On 4/25/22 10:15, Martin Fernandez wrote:
> +/**
> + * e820__range_remove() - Remove an address range from e820_table.
> + * @start: Start of the address range.
> + * @size: Size of the address range.
> + * @old_type: Type of the entries that we want to remove.
> + * @check_type: Bool to decide if ignore @old_type or not.
> + *
> + * Remove [@start, @start + @size) from e820_table. If @check_type is
> + * true remove only entries with type @old_type.
> + *
> + * Return: The size removed.
> + */

The refactoring looks promising.  But, there's a *LOT* of kerneldoc
noise, like:

> + * @table: Target e820_table.
> + * @start: Start of the range.
> + * @size: Size of the range.

and this:

> + * struct e820_type_updater_data - Helper type for
> + * __e820__range_update().
> + * @old_type: old_type parameter of __e820__range_update().
> + * @new_type: new_type parameter of __e820__range_update().

Those are just a pure waste of bytes.  I suspect some more judicious
function comments would also make the diffstat look more palatable.

Also, in general, the naming is a bit verbose.  You might want to trim
some of those names down, like:

> +static bool __init crypto_updater__should_update(const struct e820_entry *entry,
> +						 const void *data)
> +{
> +	const struct e820_crypto_updater_data *crypto_updater_data =
> +		(const struct e820_crypto_updater_data *)data;

Those are just some high-level comments.  This also needs some really
careful review of the refactoring to make sure that it doesn't break any
of the existing e820 users.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 5/8] x86/e820: Refactor e820__range_remove
  2022-04-26 15:10   ` Dave Hansen
@ 2022-04-26 17:37     ` Martin Fernandez
  2022-04-26 17:55       ` Dave Hansen
  0 siblings, 1 reply; 20+ messages in thread
From: Martin Fernandez @ 2022-04-26 17:37 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, rppt, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On 4/26/22, Dave Hansen <dave.hansen@intel.com> wrote:
> On 4/25/22 10:15, Martin Fernandez wrote:
>> +/**
>> + * e820__range_remove() - Remove an address range from e820_table.
>> + * @start: Start of the address range.
>> + * @size: Size of the address range.
>> + * @old_type: Type of the entries that we want to remove.
>> + * @check_type: Bool to decide if ignore @old_type or not.
>> + *
>> + * Remove [@start, @start + @size) from e820_table. If @check_type is
>> + * true remove only entries with type @old_type.
>> + *
>> + * Return: The size removed.
>> + */
>
> The refactoring looks promising.  But, there's a *LOT* of kerneldoc
> noise, like:
>
>> + * @table: Target e820_table.
>> + * @start: Start of the range.
>> + * @size: Size of the range.
>
> and this:
>
>> + * struct e820_type_updater_data - Helper type for
>> + * __e820__range_update().
>> + * @old_type: old_type parameter of __e820__range_update().
>> + * @new_type: new_type parameter of __e820__range_update().
>
> Those are just a pure waste of bytes.  I suspect some more judicious
> function comments would also make the diffstat look more palatable.
>

I can get rid off of the kerneldocs and just put normal comments for some
functions that really need them.

> Also, in general, the naming is a bit verbose.  You might want to trim
> some of those names down, like:
>
>> +static bool __init crypto_updater__should_update(const struct e820_entry
>> *entry,
>> +						 const void *data)
>> +{
>> +	const struct e820_crypto_updater_data *crypto_updater_data =
>> +		(const struct e820_crypto_updater_data *)data;
>

Yes I agree on this. Do you have any suggestions for these kind of
functions? I want to explicitly state that these functions are in some of
namespace and are different of the other ones.

In the end I don't think this is very harmful since these functions are one-time
used (in a single place), is not the case that you have to use them everywhere..

> Those are just some high-level comments.  This also needs some really
> careful review of the refactoring to make sure that it doesn't break any
> of the existing e820 users.
>

I'm glad to hear more people's thoughts on this. Thanks for the feedback.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v7 5/8] x86/e820: Refactor e820__range_remove
  2022-04-26 17:37     ` Martin Fernandez
@ 2022-04-26 17:55       ` Dave Hansen
  0 siblings, 0 replies; 20+ messages in thread
From: Dave Hansen @ 2022-04-26 17:55 UTC (permalink / raw)
  To: Martin Fernandez
  Cc: linux-kernel, linux-efi, platform-driver-x86, linux-mm, tglx,
	mingo, bp, dave.hansen, x86, hpa, ardb, dvhart, andy, gregkh,
	rafael, rppt, akpm, daniel.gutson, hughsient, alex.bazhaniuk,
	alison.schofield, keescook

On 4/26/22 10:37, Martin Fernandez wrote:
>> Also, in general, the naming is a bit verbose.  You might want to trim
>> some of those names down, like:
>>
>>> +static bool __init crypto_updater__should_update(const struct e820_entry
>>> *entry,
>>> +						 const void *data)
>>> +{
>>> +	const struct e820_crypto_updater_data *crypto_updater_data =
>>> +		(const struct e820_crypto_updater_data *)data;
> Yes I agree on this. Do you have any suggestions for these kind of
> functions? I want to explicitly state that these functions are in some of
> namespace and are different of the other ones.
> 
> In the end I don't think this is very harmful since these functions are one-time
> used (in a single place), is not the case that you have to use them everywhere..

Let's just start with the fact that this is a pointer to a structure
containing an enum that represents a single bit.  You could just pass
around an address to a bool:

	bool crypto_capable = *(bool *)data;

or even just pass and use the 'void *data' pointer as a value directly:

	bool crypto_capable = (bool)data;

That, for one, would get rid of some of the naming craziness.

If it were me, and I *really* wanted to keep the full types, I would
have just condensed that line down to:

	struct e820_crypto_updater_data *crypto_data = data;

Yeah, it _can_ be const, but it buys you practically nothing in this
case and only hurts readability.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2022-04-26 17:53 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-25 17:15 [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Martin Fernandez
2022-04-25 17:15 ` [PATCH v7 1/8] mm/memblock: Tag memblocks with crypto capabilities Martin Fernandez
2022-04-26  6:10   ` Mike Rapoport
2022-04-26 12:59     ` Martin Fernandez
2022-04-26 13:20       ` Mike Rapoport
2022-04-26 13:25         ` Daniel Gutson
2022-04-25 17:15 ` [PATCH v7 2/8] mm/mmzone: Tag pg_data_t " Martin Fernandez
2022-04-26  6:16   ` Mike Rapoport
2022-04-25 17:15 ` [PATCH v7 3/8] x86/e820: Add infrastructure to refactor e820__range_{update,remove} Martin Fernandez
2022-04-25 17:15 ` [PATCH v7 4/8] x86/e820: Refactor __e820__range_update Martin Fernandez
2022-04-25 17:15 ` [PATCH v7 5/8] x86/e820: Refactor e820__range_remove Martin Fernandez
2022-04-26 15:10   ` Dave Hansen
2022-04-26 17:37     ` Martin Fernandez
2022-04-26 17:55       ` Dave Hansen
2022-04-25 17:15 ` [PATCH v7 6/8] x86/e820: Tag e820_entry with crypto capabilities Martin Fernandez
2022-04-25 17:15 ` [PATCH v7 7/8] x86/efi: Mark e820_entries as crypto capable from EFI memmap Martin Fernandez
2022-04-25 17:15 ` [PATCH v7 8/8] drivers/node: Show in sysfs node's crypto capabilities Martin Fernandez
2022-04-26  6:16   ` Mike Rapoport
2022-04-26 13:01     ` Martin Fernandez
2022-04-25 17:23 ` [PATCH v7 0/8] x86: Show in sysfs if a memory node is able to do encryption Andrew Morton

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.