[PATCH v11 2/3] x86/mm: refactor __set_clr_pte_enc()

From: Ashish Kalra
Date: Tue Jul 02 2024 - 15:58:22 EST


From: Ashish Kalra <ashish.kalra@xxxxxxx>

Refactor __set_clr_pte_enc() and add two new helper functions to
set/clear PTE C-bit from early SEV/SNP initialization code and
later during normal system operations and shutdown/kexec.

Signed-off-by: Ashish Kalra <ashish.kalra@xxxxxxx>
---
arch/x86/include/asm/sev.h | 9 +++++++
arch/x86/mm/mem_encrypt_amd.c | 47 +++++++++++++++++++++++++++++------
2 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index ac5886ce252e..4f3fd913aadb 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -348,6 +348,10 @@ u64 snp_get_unsupported_features(u64 status);
u64 sev_get_status(void);
void sev_show_status(void);
void snp_update_svsm_ca(void);
+int prep_set_clr_pte_enc(pte_t *kpte, int level, int enc, void *va,
+ unsigned long *ret_pfn, unsigned long *ret_pa,
+ unsigned long *ret_size, pgprot_t *ret_new_prot);
+void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot);

#else /* !CONFIG_AMD_MEM_ENCRYPT */

@@ -384,6 +388,11 @@ static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
static inline u64 sev_get_status(void) { return 0; }
static inline void sev_show_status(void) { }
static inline void snp_update_svsm_ca(void) { }
+static inline int
+prep_set_clr_pte_enc(pte_t *kpte, int level, int enc, void *va,
+ unsigned long *ret_pfn, unsigned long *ret_pa,
+ unsigned long *ret_size, pgprot_t *ret_new_prot) { }
+static inline void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) { }

#endif /* CONFIG_AMD_MEM_ENCRYPT */

diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
index 86a476a426c2..42a35040aaf9 100644
--- a/arch/x86/mm/mem_encrypt_amd.c
+++ b/arch/x86/mm/mem_encrypt_amd.c
@@ -311,15 +311,16 @@ static int amd_enc_status_change_finish(unsigned long vaddr, int npages, bool en
return 0;
}

-static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
+int prep_set_clr_pte_enc(pte_t *kpte, int level, int enc, void *va,
+ unsigned long *ret_pfn, unsigned long *ret_pa,
+ unsigned long *ret_size, pgprot_t *ret_new_prot)
{
pgprot_t old_prot, new_prot;
unsigned long pfn, pa, size;
- pte_t new_pte;

pfn = pg_level_to_pfn(level, kpte, &old_prot);
if (!pfn)
- return;
+ return 1;

new_prot = old_prot;
if (enc)
@@ -329,7 +330,7 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)

/* If prot is same then do nothing. */
if (pgprot_val(old_prot) == pgprot_val(new_prot))
- return;
+ return 1;

pa = pfn << PAGE_SHIFT;
size = page_level_size(level);
@@ -339,7 +340,39 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
* physical page attribute from C=1 to C=0 or vice versa. Flush the
* caches to ensure that data gets accessed with the correct C-bit.
*/
- clflush_cache_range(__va(pa), size);
+ if (va)
+ clflush_cache_range(va, size);
+ else
+ clflush_cache_range(__va(pa), size);
+
+ if (ret_new_prot)
+ *ret_new_prot = new_prot;
+ if (ret_size)
+ *ret_size = size;
+ if (ret_pfn)
+ *ret_pfn = pfn;
+ if (ret_pa)
+ *ret_pa = pa;
+
+ return 0;
+}
+
+void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot)
+{
+ pte_t new_pte;
+
+ /* Change the page encryption mask. */
+ new_pte = pfn_pte(pfn, new_prot);
+ set_pte_atomic(kpte, new_pte);
+}
+
+static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
+{
+ unsigned long pfn, pa, size;
+ pgprot_t new_prot;
+
+ if (prep_set_clr_pte_enc(kpte, level, enc, NULL, &pfn, &pa, &size, &new_prot))
+ return;

/* Encrypt/decrypt the contents in-place */
if (enc) {
@@ -354,9 +387,7 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1);
}

- /* Change the page encryption mask. */
- new_pte = pfn_pte(pfn, new_prot);
- set_pte_atomic(kpte, new_pte);
+ set_pte_enc_mask(kpte, pfn, new_prot);

/*
* If page is set encrypted in the page table, then update the RMP table to
--
2.34.1