LKML Archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Apply RMP table fixups for kexec.
@ 2024-04-15 21:08 Ashish Kalra
  2024-04-15 21:09 ` [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally Ashish Kalra
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Ashish Kalra @ 2024-04-15 21:08 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: bp, thomas.lendacky, michael.roth, x86, linux-kernel

From: Ashish Kalra <ashish.kalra@amd.com>

Handle cases where the RMP table placement in the BIOS is
not 2M aligned and then the kexec kernel could try to allocate
from within that chunk and that causes a fatal RMP fault.
Check if RMP table start & end physical range in e820_table
is not aligned to 2MB and in that case use e820__range_update()
to map this range to reserved.

The callback to apply these RMP table fixups needs to be called
after the e820 tables are setup/populated and before the e820 map
has been converted to the standard Linux memory resources and e820 map
is no longer used and modifying it has no effect.

v2:
- Remove overriding e820__memory_setup_default() to invoke
  snp_rmptable_e820_fixup() to apply the RMP table fixups.
- This callback snp_rmptable_e820_fixup() is now invoked
  after e820__memory_setup() and before e820__reserve_resources().
- Expose e820 API interfaces to update e820_table_kexec and
  e820_table_firmware externally.
- snp_rmptable_e820_fixup() now calls these new external API
  interfaces to update e820_table_kexec and e820_table_firmware.


Ashish Kalra (2):
  x86/e820: Expose API to update e820 kexec and firmware tables
    externally.
  x86/sev: Add callback to apply RMP table fixups for kexec.

 arch/x86/include/asm/e820/api.h |  3 +++
 arch/x86/include/asm/sev.h      |  2 ++
 arch/x86/kernel/e820.c          |  7 +++++-
 arch/x86/mm/mem_encrypt.c       |  3 +++
 arch/x86/virt/svm/sev.c         | 44 +++++++++++++++++++++++++++++++++
 5 files changed, 58 insertions(+), 1 deletion(-)

-- 
2.34.1


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

* [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally.
  2024-04-15 21:08 [PATCH v2 0/2] Apply RMP table fixups for kexec Ashish Kalra
@ 2024-04-15 21:09 ` Ashish Kalra
  2024-04-20 11:20   ` Borislav Petkov
  2024-04-15 21:09 ` [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec Ashish Kalra
  2024-04-20 11:08 ` [PATCH v2 0/2] Apply " Borislav Petkov
  2 siblings, 1 reply; 11+ messages in thread
From: Ashish Kalra @ 2024-04-15 21:09 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: bp, thomas.lendacky, michael.roth, x86, linux-kernel

From: Ashish Kalra <ashish.kalra@amd.com>

Export the API interfaces to update the e820_table_kexec and
e820_table_firmware.

Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 arch/x86/include/asm/e820/api.h | 3 +++
 arch/x86/kernel/e820.c          | 7 ++++++-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h
index e8f58ddd06d9..09fe1ddcdf2b 100644
--- a/arch/x86/include/asm/e820/api.h
+++ b/arch/x86/include/asm/e820/api.h
@@ -18,6 +18,9 @@ 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_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type  new_type);
+extern u64 e820__range_update_firmware(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
+
 extern void e820__print_table(char *who);
 extern int  e820__update_table(struct e820_table *table);
 extern void e820__update_table_print(void);
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 6f1b379e3b38..c59d1bbbe3f2 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -532,7 +532,12 @@ u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum
 	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)
+u64 __init e820__range_update_firmware(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
+{
+	return __e820__range_update(e820_table_firmware, start, size, old_type, new_type);
+}
+
+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.34.1


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

* [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
  2024-04-15 21:08 [PATCH v2 0/2] Apply RMP table fixups for kexec Ashish Kalra
  2024-04-15 21:09 ` [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally Ashish Kalra
@ 2024-04-15 21:09 ` Ashish Kalra
  2024-04-20 13:05   ` Borislav Petkov
  2024-04-20 11:08 ` [PATCH v2 0/2] Apply " Borislav Petkov
  2 siblings, 1 reply; 11+ messages in thread
From: Ashish Kalra @ 2024-04-15 21:09 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: bp, thomas.lendacky, michael.roth, x86, linux-kernel

From: Ashish Kalra <ashish.kalra@amd.com>

Handle cases where the RMP table placement in the BIOS is
not 2M aligned and then the kexec kernel could try to allocate
from within that chunk and that causes a fatal RMP fault.
Check if RMP table start & end physical range in e820_table
is not aligned to 2MB and in that case use e820__range_update()
to map this range to reserved.

The callback to apply these RMP table fixups needs to be called
after the e820 tables are setup/populated and before the e820 map
has been converted to the standard Linux memory resources and e820 map
is no longer used and modifying it has no effect.

Fixes: c3b86e61b756 ("x86/cpufeatures: Enable/unmask SEV-SNP CPU feature")
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 arch/x86/include/asm/sev.h |  2 ++
 arch/x86/mm/mem_encrypt.c  |  3 +++
 arch/x86/virt/svm/sev.c    | 44 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 7f57382afee4..6600ac467cf9 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -269,6 +269,7 @@ int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immut
 int rmp_make_shared(u64 pfn, enum pg_level level);
 void snp_leak_pages(u64 pfn, unsigned int npages);
 void kdump_sev_callback(void);
+void snp_rmptable_e820_fixup(void);
 #else
 static inline bool snp_probe_rmptable_info(void) { return false; }
 static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
@@ -282,6 +283,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
 static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
 static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
 static inline void kdump_sev_callback(void) { }
+static inline void snp_rmptable_e820_fixup(void) {}
 #endif
 
 #endif
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 6f3b3e028718..765ce94e4b89 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -102,6 +102,9 @@ void __init mem_encrypt_setup_arch(void)
 	phys_addr_t total_mem = memblock_phys_mem_size();
 	unsigned long size;
 
+	if (cpu_feature_enabled(X86_FEATURE_SEV_SNP))
+		snp_rmptable_e820_fixup();
+
 	if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
 		return;
 
diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
index ab0e8448bb6e..d999ff7f1671 100644
--- a/arch/x86/virt/svm/sev.c
+++ b/arch/x86/virt/svm/sev.c
@@ -163,6 +163,50 @@ bool snp_probe_rmptable_info(void)
 	return true;
 }
 
+/*
+ * Callback to do any RMP table fixups, needs to be called
+ * after e820__memory_setup(), after the e820 tables are
+ * setup/populated and before e820__reserve_resources(), before
+ * the e820 map has been converted to the standard Linux memory
+ * resources and e820 map is no longer used and modifying it
+ * has no effect.
+ */
+void __init snp_rmptable_e820_fixup(void)
+{
+	u64 pa;
+
+	/*
+	 * Handle cases where the RMP table placement in the BIOS is not 2M aligned
+	 * and then the kexec kernel could try to allocate from within that chunk
+	 * and that causes a fatal RMP fault. Check if RMP table start & end
+	 * physical range in e820_table is not aligned to 2MB and in that case use
+	 * e820__range_update() to map this range to reserved, e820__range_update()
+	 * nicely handles partial range update and also merges any consecutive
+	 * ranges of the same type.
+	 */
+	pa = probed_rmp_base;
+	if (!IS_ALIGNED(pa, PMD_SIZE)) {
+		pa = ALIGN_DOWN(pa, PMD_SIZE);
+		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
+			pr_info("Reserving start of RMP table on a 2MB boundary [0x%016llx]\n", pa);
+			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+		}
+	}
+
+	pa = probed_rmp_base + probed_rmp_size;
+	if (!IS_ALIGNED(pa, PMD_SIZE)) {
+		pa = ALIGN_DOWN(pa, PMD_SIZE);
+		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
+			pr_info("Reserving end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
+			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+		}
+	}
+}
+
 /*
  * Do the necessary preparations which are verified by the firmware as
  * described in the SNP_INIT_EX firmware command description in the SNP
-- 
2.34.1


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

* Re: [PATCH v2 0/2] Apply RMP table fixups for kexec.
  2024-04-15 21:08 [PATCH v2 0/2] Apply RMP table fixups for kexec Ashish Kalra
  2024-04-15 21:09 ` [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally Ashish Kalra
  2024-04-15 21:09 ` [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec Ashish Kalra
@ 2024-04-20 11:08 ` Borislav Petkov
  2024-04-24 19:10   ` Kalra, Ashish
  2 siblings, 1 reply; 11+ messages in thread
From: Borislav Petkov @ 2024-04-20 11:08 UTC (permalink / raw)
  To: Ashish Kalra; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

Drop linux-tip-commits@vger.kernel.org from Cc.

On Mon, Apr 15, 2024 at 09:08:56PM +0000, Ashish Kalra wrote:
> From: Ashish Kalra <ashish.kalra@amd.com>
> 
> Handle cases where the RMP table placement in the BIOS is
> not 2M aligned and then the kexec kernel could try to allocate
> from within that chunk and that causes a fatal RMP fault.

Is this something that happens on existing systems currently so that it
needs to be fixed upstream?

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

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

* Re: [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally.
  2024-04-15 21:09 ` [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally Ashish Kalra
@ 2024-04-20 11:20   ` Borislav Petkov
  0 siblings, 0 replies; 11+ messages in thread
From: Borislav Petkov @ 2024-04-20 11:20 UTC (permalink / raw)
  To: Ashish Kalra
  Cc: linux-tip-commits, thomas.lendacky, michael.roth, x86,
	linux-kernel

On Mon, Apr 15, 2024 at 09:09:10PM +0000, Ashish Kalra wrote:
> -static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type  new_type)
> +u64 __init e820__range_update_firmware(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
> +{
> +	return __e820__range_update(e820_table_firmware, start, size, old_type, new_type);
> +}
> +
> +u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type  new_type)

Yah, no point in defining silly wrappers _kexec() and _firmware() if the
actual e820 tables are already exported in asm/e820/api.h

You need a single

e820__range_update_table(struct e820_table *t, ..)

helper and move all current and future users to it while leaving
e820__range_update() alone which works on the e820_table.

As a future cleanup, e820__range_update() should be changed to use the
new e820__range_update_table() helper and then perhaps all code should
be converted back to a new

e820__range_update()

which takes a table as a first argument.

But the cleanup can go in later, after the current issue has been
resolved.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

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

* Re: [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
  2024-04-15 21:09 ` [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec Ashish Kalra
@ 2024-04-20 13:05   ` Borislav Petkov
  2024-04-24 23:48     ` Kalra, Ashish
  0 siblings, 1 reply; 11+ messages in thread
From: Borislav Petkov @ 2024-04-20 13:05 UTC (permalink / raw)
  To: Ashish Kalra; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

On Mon, Apr 15, 2024 at 09:09:24PM +0000, Ashish Kalra wrote:

> Subject: Re: [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
										       ^
patch subject doesn't need a fullstop:						-------|

> From: Ashish Kalra <ashish.kalra@amd.com>
> 
> Handle cases where the RMP table placement in the BIOS is
> not 2M aligned and then the kexec kernel could try to allocate
> from within that chunk and that causes a fatal RMP fault.

> Check if RMP table start & end physical range in e820_table
> is not aligned to 2MB and in that case use e820__range_update()
> to map this range to reserved.

Why do you keep explaining in your commit messages what a patch does?

Do not talk about *what* the patch is doing in the commit message - that
should be obvious from the diff itself. Rather, concentrate on the *why*
it needs to be done.

Imagine one fine day you're doing git archeology, you find the place in
the code about which you want to find out why it was changed the way it
is now.

You do git annotate <filename> ... find the line, see the commit id and
you do:

git show <commit id>

You read the commit message and there's just gibberish and nothing's
explaining *why* that change was done. And you start scratching your
head, trying to figure out why. Because the damn commit message is worth
sh*t.

> The callback to apply these RMP table fixups needs to be called
> after the e820 tables are setup/populated and before the e820 map
> has been converted to the standard Linux memory resources and e820 map
> is no longer used and modifying it has no effect.

This commit message is not even trying to summarize what was figured out
in previous review in the thread here:

https://lore.kernel.org/r/20240312184757.52699-1-Ashish.Kalra@amd.com

Please restructure this commit message using all the info from that
thread and use this structure, for example:

1. Prepare the context for the explanation briefly.

2. Explain the problem at hand.

3. "It happens because of <...>"

4. "Fix it by doing X"

5. "(Potentially do Y)."

And some of those above are optional depending on the issue being
explained.

For more detailed info, see
Documentation/process/submitting-patches.rst,
Section "2) Describe your changes".

Also, to the tone, from Documentation/process/submitting-patches.rst:

 "Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
  instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
  to do frotz", as if you are giving orders to the codebase to change
  its behaviour."

> Fixes: c3b86e61b756 ("x86/cpufeatures: Enable/unmask SEV-SNP CPU feature")
> Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
> ---
>  arch/x86/include/asm/sev.h |  2 ++
>  arch/x86/mm/mem_encrypt.c  |  3 +++
>  arch/x86/virt/svm/sev.c    | 44 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 49 insertions(+)
> 
> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> index 7f57382afee4..6600ac467cf9 100644
> --- a/arch/x86/include/asm/sev.h
> +++ b/arch/x86/include/asm/sev.h
> @@ -269,6 +269,7 @@ int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immut
>  int rmp_make_shared(u64 pfn, enum pg_level level);
>  void snp_leak_pages(u64 pfn, unsigned int npages);
>  void kdump_sev_callback(void);
> +void snp_rmptable_e820_fixup(void);
>  #else
>  static inline bool snp_probe_rmptable_info(void) { return false; }
>  static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
> @@ -282,6 +283,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
>  static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
>  static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
>  static inline void kdump_sev_callback(void) { }
> +static inline void snp_rmptable_e820_fixup(void) {}
>  #endif
>  
>  #endif
> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 6f3b3e028718..765ce94e4b89 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -102,6 +102,9 @@ void __init mem_encrypt_setup_arch(void)
>  	phys_addr_t total_mem = memblock_phys_mem_size();
>  	unsigned long size;
>  
> +	if (cpu_feature_enabled(X86_FEATURE_SEV_SNP))

We use CC_ATTR_HOST_SEV_SNP for host SNP support checks, including RMP
table viability.

Also, why isn't this called in snp_init()?

If there's a reason why (I think there is) put that reason as a comment
above it why this thing needs to be called here exactly.

> +		snp_rmptable_e820_fixup();

IOW, point to the comment above that function's definition.

> +
>  	if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
>  		return;
>  
> diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
> index ab0e8448bb6e..d999ff7f1671 100644
> --- a/arch/x86/virt/svm/sev.c
> +++ b/arch/x86/virt/svm/sev.c
> @@ -163,6 +163,50 @@ bool snp_probe_rmptable_info(void)
>  	return true;
>  }
>  
> +/*
> + * Callback to do any RMP table fixups, needs to be called
> + * after e820__memory_setup(), after the e820 tables are
> + * setup/populated and before e820__reserve_resources(), before
> + * the e820 map has been converted to the standard Linux memory
> + * resources and e820 map is no longer used and modifying it
> + * has no effect.
> + */
> +void __init snp_rmptable_e820_fixup(void)
> +{
> +	u64 pa;
> +
> +	/*
> +	 * Handle cases where the RMP table placement in the BIOS is not 2M aligned
> +	 * and then the kexec kernel could try to allocate from within that chunk
> +	 * and that causes a fatal RMP fault.

Merge this comment with the one above the function and put it all there.

> Check if RMP table start & end
> +	 * physical range in e820_table is not aligned to 2MB and in that case use
> +	 * e820__range_update() to map this range to reserved, e820__range_update()
> +	 * nicely handles partial range update and also merges any consecutive
> +	 * ranges of the same type.
> +	 */

This comment talks about what this does and is kinda obvious but then
talks about e820__range_update() and not the other ones. Just put the
gist of what this is supposed to do and do not explain the code step by
step.

What is really missing here and what is not really trivial is why all
three e820 tables need updating.

> +	pa = probed_rmp_base;
> +	if (!IS_ALIGNED(pa, PMD_SIZE)) {
> +		pa = ALIGN_DOWN(pa, PMD_SIZE);
> +		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
> +			pr_info("Reserving start of RMP table on a 2MB boundary [0x%016llx]\n", pa);
> +			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +		}
> +	}
> +
> +	pa = probed_rmp_base + probed_rmp_size;
> +	if (!IS_ALIGNED(pa, PMD_SIZE)) {
> +		pa = ALIGN_DOWN(pa, PMD_SIZE);
> +		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
> +			pr_info("Reserving end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
> +			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +		}
> +	}
> +}

Ontop for less duplication:

diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
index be17661fee9b..118dfe61f80e 100644
--- a/arch/x86/virt/svm/sev.c
+++ b/arch/x86/virt/svm/sev.c
@@ -163,6 +163,21 @@ bool snp_probe_rmptable_info(void)
 	return true;
 }
 
+static void __init __snp_e820_tables_fixup(u64 pa)
+{
+	if (IS_ALIGNED(pa, PMD_SIZE))
+		return;
+
+	pa = ALIGN_DOWN(pa, PMD_SIZE);
+	if (!e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM))
+		return;
+
+	pr_info("Reserving chunk of RMP table on a 2MB boundary [0x%016llx]\n", pa);
+	e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+	e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+	e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+}
+
 /*
  * Callback to do any RMP table fixups, needs to be called
  * after e820__memory_setup(), after the e820 tables are
@@ -173,8 +188,6 @@ bool snp_probe_rmptable_info(void)
  */
 void __init snp_rmptable_e820_fixup(void)
 {
-	u64 pa;
-
 	/*
 	 * Handle cases where the RMP table placement in the BIOS is not 2M aligned
 	 * and then the kexec kernel could try to allocate from within that chunk
@@ -184,27 +197,8 @@ void __init snp_rmptable_e820_fixup(void)
 	 * nicely handles partial range update and also merges any consecutive
 	 * ranges of the same type.
 	 */
-	pa = probed_rmp_base;
-	if (!IS_ALIGNED(pa, PMD_SIZE)) {
-		pa = ALIGN_DOWN(pa, PMD_SIZE);
-		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
-			pr_info("Reserving start of RMP table on a 2MB boundary [0x%016llx]\n", pa);
-			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
-			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
-			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
-		}
-	}
-
-	pa = probed_rmp_base + probed_rmp_size;
-	if (!IS_ALIGNED(pa, PMD_SIZE)) {
-		pa = ALIGN_DOWN(pa, PMD_SIZE);
-		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
-			pr_info("Reserving end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
-			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
-			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
-			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
-		}
-	}
+	__snp_e820_tables_fixup(probed_rmp_base);
+	__snp_e820_tables_fixup(probed_rmp_base + probed_rmp_size);
 }
 
 /*

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

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

* Re: [PATCH v2 0/2] Apply RMP table fixups for kexec.
  2024-04-20 11:08 ` [PATCH v2 0/2] Apply " Borislav Petkov
@ 2024-04-24 19:10   ` Kalra, Ashish
  2024-04-26 12:49     ` Borislav Petkov
  0 siblings, 1 reply; 11+ messages in thread
From: Kalra, Ashish @ 2024-04-24 19:10 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

Hello Boris,

On 4/20/2024 6:08 AM, Borislav Petkov wrote:
> Drop linux-tip-commits@vger.kernel.org from Cc.
>
> On Mon, Apr 15, 2024 at 09:08:56PM +0000, Ashish Kalra wrote:
>> From: Ashish Kalra <ashish.kalra@amd.com>
>>
>> Handle cases where the RMP table placement in the BIOS is
>> not 2M aligned and then the kexec kernel could try to allocate
>> from within that chunk and that causes a fatal RMP fault.
> Is this something that happens on existing systems currently so that it
> needs to be fixed upstream?

Patch 2/2 - includes the following Fixes tag, do i need to include the 
Fixes tag in the cover letter too ?

Fixes: c3b86e61b756 ("x86/cpufeatures: Enable/unmask SEV-SNP CPU feature")

Thanks,
Ashish


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

* Re: [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
  2024-04-20 13:05   ` Borislav Petkov
@ 2024-04-24 23:48     ` Kalra, Ashish
  2024-04-26 12:58       ` Borislav Petkov
  0 siblings, 1 reply; 11+ messages in thread
From: Kalra, Ashish @ 2024-04-24 23:48 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

Hello Boris,

> Subject: Re: [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
>
> From: Ashish Kalra<ashish.kalra@amd.com>

<snip>
> Why do you keep explaining in your commit messages what a patch does?
I will fix the commit message.
>> Fixes: c3b86e61b756 ("x86/cpufeatures: Enable/unmask SEV-SNP CPU feature")
>> Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
>> ---
>>   arch/x86/include/asm/sev.h |  2 ++
>>   arch/x86/mm/mem_encrypt.c  |  3 +++
>>   arch/x86/virt/svm/sev.c    | 44 ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 49 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
>> index 7f57382afee4..6600ac467cf9 100644
>> --- a/arch/x86/include/asm/sev.h
>> +++ b/arch/x86/include/asm/sev.h
>> @@ -269,6 +269,7 @@ int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immut
>>   int rmp_make_shared(u64 pfn, enum pg_level level);
>>   void snp_leak_pages(u64 pfn, unsigned int npages);
>>   void kdump_sev_callback(void);
>> +void snp_rmptable_e820_fixup(void);
>>   #else
>>   static inline bool snp_probe_rmptable_info(void) { return false; }
>>   static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
>> @@ -282,6 +283,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
>>   static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
>>   static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
>>   static inline void kdump_sev_callback(void) { }
>> +static inline void snp_rmptable_e820_fixup(void) {}
>>   #endif
>>   
>>   #endif
>> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
>> index 6f3b3e028718..765ce94e4b89 100644
>> --- a/arch/x86/mm/mem_encrypt.c
>> +++ b/arch/x86/mm/mem_encrypt.c
>> @@ -102,6 +102,9 @@ void __init mem_encrypt_setup_arch(void)
>>   	phys_addr_t total_mem = memblock_phys_mem_size();
>>   	unsigned long size;
>>   
>> +	if (cpu_feature_enabled(X86_FEATURE_SEV_SNP))
> We use CC_ATTR_HOST_SEV_SNP for host SNP support checks, including RMP
> table viability.
Ok.
>
> Also, why isn't this called in snp_init()?
>
> If there's a reason why (I think there is) put that reason as a comment
> above it why this thing needs to be called here exactly.

This callback needs to be invoked as part of setup_arch() as it needs 
e820 table to be setup in e820__memory_setup() before the callback is 
invoked and snp_init() is called from sme_enable() in kernel/head_64.S 
(startup_64), which is much before start_kernel() -> setup_arch() is 
invoked.

I will add the comment here.

>> +		snp_rmptable_e820_fixup();
> IOW, point to the comment above that function's definition.
>
>> +
>>   	if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
>>   		return;
>>   
>> diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
>> index ab0e8448bb6e..d999ff7f1671 100644
>> --- a/arch/x86/virt/svm/sev.c
>> +++ b/arch/x86/virt/svm/sev.c
>> @@ -163,6 +163,50 @@ bool snp_probe_rmptable_info(void)
>>   	return true;
>>   }
>>   
>> +/*
>> + * Callback to do any RMP table fixups, needs to be called
>> + * after e820__memory_setup(), after the e820 tables are
>> + * setup/populated and before e820__reserve_resources(), before
>> + * the e820 map has been converted to the standard Linux memory
>> + * resources and e820 map is no longer used and modifying it
>> + * has no effect.
>> + */
>> +void __init snp_rmptable_e820_fixup(void)
>> +{
>> +	u64 pa;
>> +
>> +	/*
>> +	 * Handle cases where the RMP table placement in the BIOS is not 2M aligned
>> +	 * and then the kexec kernel could try to allocate from within that chunk
>> +	 * and that causes a fatal RMP fault.
> Merge this comment with the one above the function and put it all there.
Ok.
>> Check if RMP table start & end
>> +	 * physical range in e820_table is not aligned to 2MB and in that case use
>> +	 * e820__range_update() to map this range to reserved, e820__range_update()
>> +	 * nicely handles partial range update and also merges any consecutive
>> +	 * ranges of the same type.
>> +	 */
> This comment talks about what this does and is kinda obvious but then
> talks about e820__range_update() and not the other ones. Just put the
> gist of what this is supposed to do and do not explain the code step by
> step.
>
> What is really missing here and what is not really trivial is why all
> three e820 tables need updating.
I will add all these details.
>
>> +	pa = probed_rmp_base;
>> +	if (!IS_ALIGNED(pa, PMD_SIZE)) {
>> +		pa = ALIGN_DOWN(pa, PMD_SIZE);
>> +		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
>> +			pr_info("Reserving start of RMP table on a 2MB boundary [0x%016llx]\n", pa);
>> +			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
>> +			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
>> +			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
>> +		}
>> +	}
>> +
>> +	pa = probed_rmp_base + probed_rmp_size;
>> +	if (!IS_ALIGNED(pa, PMD_SIZE)) {
>> +		pa = ALIGN_DOWN(pa, PMD_SIZE);
>> +		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
>> +			pr_info("Reserving end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
>> +			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
>> +			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
>> +			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
>> +		}
>> +	}
>> +}
> Ontop for less duplication:
>
> diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
> index be17661fee9b..118dfe61f80e 100644
> --- a/arch/x86/virt/svm/sev.c
> +++ b/arch/x86/virt/svm/sev.c
> @@ -163,6 +163,21 @@ bool snp_probe_rmptable_info(void)
>   	return true;
>   }
>   
> +static void __init __snp_e820_tables_fixup(u64 pa)
> +{
> +	if (IS_ALIGNED(pa, PMD_SIZE))
> +		return;
> +
> +	pa = ALIGN_DOWN(pa, PMD_SIZE);
> +	if (!e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM))
> +		return;
> +
> +	pr_info("Reserving chunk of RMP table on a 2MB boundary [0x%016llx]\n", pa);
> +	e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +	e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +	e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> +}
> +
>   /*
>    * Callback to do any RMP table fixups, needs to be called
>    * after e820__memory_setup(), after the e820 tables are
> @@ -173,8 +188,6 @@ bool snp_probe_rmptable_info(void)
>    */
>   void __init snp_rmptable_e820_fixup(void)
>   {
> -	u64 pa;
> -
>   	/*
>   	 * Handle cases where the RMP table placement in the BIOS is not 2M aligned
>   	 * and then the kexec kernel could try to allocate from within that chunk
> @@ -184,27 +197,8 @@ void __init snp_rmptable_e820_fixup(void)
>   	 * nicely handles partial range update and also merges any consecutive
>   	 * ranges of the same type.
>   	 */
> -	pa = probed_rmp_base;
> -	if (!IS_ALIGNED(pa, PMD_SIZE)) {
> -		pa = ALIGN_DOWN(pa, PMD_SIZE);
> -		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
> -			pr_info("Reserving start of RMP table on a 2MB boundary [0x%016llx]\n", pa);
> -			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> -			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> -			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> -		}
> -	}
> -
> -	pa = probed_rmp_base + probed_rmp_size;
> -	if (!IS_ALIGNED(pa, PMD_SIZE)) {
> -		pa = ALIGN_DOWN(pa, PMD_SIZE);
> -		if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
> -			pr_info("Reserving end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
> -			e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> -			e820__range_update_kexec(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> -			e820__range_update_firmware(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
> -		}
> -	}
> +	__snp_e820_tables_fixup(probed_rmp_base);
> +	__snp_e820_tables_fixup(probed_rmp_base + probed_rmp_size);
>   }
>   
Thanks, Ashish

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

* Re: [PATCH v2 0/2] Apply RMP table fixups for kexec.
  2024-04-24 19:10   ` Kalra, Ashish
@ 2024-04-26 12:49     ` Borislav Petkov
  0 siblings, 0 replies; 11+ messages in thread
From: Borislav Petkov @ 2024-04-26 12:49 UTC (permalink / raw)
  To: Kalra, Ashish; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

On Wed, Apr 24, 2024 at 02:10:03PM -0500, Kalra, Ashish wrote:
> Patch 2/2 - includes the following Fixes tag, do i need to include the Fixes
> tag in the cover letter too ?
> 
> Fixes: c3b86e61b756 ("x86/cpufeatures: Enable/unmask SEV-SNP CPU feature")

People slap Fixes tags on pretty much every patch nowadays. I'd prefer
it if you spell it out in the future what the problem is you're
encountering so that I can make a decision where to route the patches
through.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

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

* Re: [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
  2024-04-24 23:48     ` Kalra, Ashish
@ 2024-04-26 12:58       ` Borislav Petkov
  2024-04-26 14:56         ` Kalra, Ashish
  0 siblings, 1 reply; 11+ messages in thread
From: Borislav Petkov @ 2024-04-26 12:58 UTC (permalink / raw)
  To: Kalra, Ashish; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

On Wed, Apr 24, 2024 at 06:48:08PM -0500, Kalra, Ashish wrote:
> This callback needs to be invoked as part of setup_arch() as it needs e820
> table to be setup in e820__memory_setup() before the callback is invoked and
> snp_init() is called from sme_enable() in kernel/head_64.S (startup_64),
> which is much before start_kernel() -> setup_arch() is invoked.

So?

snp_init() still runs before e820__memory_setup(). So what's stopping
you?

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

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

* Re: [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec.
  2024-04-26 12:58       ` Borislav Petkov
@ 2024-04-26 14:56         ` Kalra, Ashish
  0 siblings, 0 replies; 11+ messages in thread
From: Kalra, Ashish @ 2024-04-26 14:56 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: thomas.lendacky, michael.roth, x86, linux-kernel

On 4/26/2024 7:58 AM, Borislav Petkov wrote:

> On Wed, Apr 24, 2024 at 06:48:08PM -0500, Kalra, Ashish wrote:
>> This callback needs to be invoked as part of setup_arch() as it needs e820
>> table to be setup in e820__memory_setup() before the callback is invoked and
>> snp_init() is called from sme_enable() in kernel/head_64.S (startup_64),
>> which is much before start_kernel() -> setup_arch() is invoked.
> So?
>
> snp_init() still runs before e820__memory_setup(). So what's stopping
> you?

As i have already explained above, snp_init() runs before 
e820__memory_setup() so we can't invoke this callback in snp_init() as 
e820 tables have still not been setup. Again to summarize, the e820 
tables are setup in e820__memory_setup() which runs after snp_init().

Additionally, RMP table also get probed after snp_init(). So this 
callback cannot be invoked in snp_init().

I have added this comment to v3 of this patch series which i posted 
yesterday, so please look at those.

Thanks, Ashish


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

end of thread, other threads:[~2024-04-26 14:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-15 21:08 [PATCH v2 0/2] Apply RMP table fixups for kexec Ashish Kalra
2024-04-15 21:09 ` [PATCH v2 1/2] x86/e820: Expose API to update e820 kexec and firmware tables externally Ashish Kalra
2024-04-20 11:20   ` Borislav Petkov
2024-04-15 21:09 ` [PATCH v2 2/2] x86/sev: Add callback to apply RMP table fixups for kexec Ashish Kalra
2024-04-20 13:05   ` Borislav Petkov
2024-04-24 23:48     ` Kalra, Ashish
2024-04-26 12:58       ` Borislav Petkov
2024-04-26 14:56         ` Kalra, Ashish
2024-04-20 11:08 ` [PATCH v2 0/2] Apply " Borislav Petkov
2024-04-24 19:10   ` Kalra, Ashish
2024-04-26 12:49     ` Borislav Petkov

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 read-only IMAP folder(s) and NNTP newsgroup(s).