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 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec