- Add shared confidential computing code which will be used by both
vendors instead of proliferating home-grown solutions for technologies
 which are pretty similar
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmI4kiQACgkQEsHwGGHe
 VUojvA//QD5VxsqPq+RAQWAFiWGHCpFed2szc2Q5eAZj6CEmXcqBOdTqaoHpJpVl
 L1uvB6oLq8WTOea0V3xGu1kfiLRuq1fo0mqZeTxe3iZ3kUk/SU0wGfTLDECB58mI
 P5A+CZFiAk4XJ/kRqJWNxmd5kIDjhlCx4ysVbPl1vm/qfS6FEGb5HUr317kbOYwK
 zw5cEajnYu2KA6bI8nGuy30vmvn97gpy98vCiCzKrcBPggO8WHiJ+kqD72BhP5em
 z7mh4aFrAPVbIMqd/Xb5La3zvP7Vii4Tz9mSUsKy/Ige+ghFZQ18LPk2yANvmWeN
 hIFDqSsESR2go0tKvSrzPln8h93hKx/TPbiF9jVMISBZFdWCGQvzCrYDHqzHFQJ1
 zHw0lxdFQimfhs5YlEumZCqq2Dc7w3OGCVfP22+t7pNhnixPT3Dlie0Ya6z/aXV3
 VNcqckDDZLijQlf0iPhbw2fBs9ErTcB3OXHKmX78Zxb4hP4WJx8QK4lMPzFkPd9H
 bTEquYQWIPsjdRTlMl50nCpNHtAzo56H01G6ZPPx/5Y7Lt38UXJERfdqBhQjNF6F
 ILPMrOn/BHU9snlqSCh7SxhRiRdafThIJHsi5zQrDC4rPvlwi5kinIzGnPyOuDbO
 qwwnPOzx855/Zw0swKrQRXaxU7lwGKo529yKZWt7r8WB12tSOao=
 =zWVD
 -----END PGP SIGNATURE-----
Merge tag 'x86_cc_for_v5.18_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 confidential computing updates from Borislav Petkov:
 - Add shared confidential computing code which will be used by both
   vendors instead of proliferating home-grown solutions for
   technologies (SEV/SNP and TDX) which are pretty similar
* tag 'x86_cc_for_v5.18_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm/cpa: Generalize __set_memory_enc_pgtable()
  x86/coco: Add API to handle encryption mask
  x86/coco: Explicitly declare type of confidential computing platform
  x86/cc: Move arch/x86/{kernel/cc_platform.c => coco/core.c}
			
			
This commit is contained in:
		
						commit
						6b9bfb1365
					
				| @ -1,4 +1,6 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| obj-$(CONFIG_ARCH_HAS_CC_PLATFORM) += coco/ | ||||
| 
 | ||||
| obj-y += entry/ | ||||
| 
 | ||||
| obj-$(CONFIG_PERF_EVENTS) += events/ | ||||
|  | ||||
							
								
								
									
										6
									
								
								arch/x86/coco/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								arch/x86/coco/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0
 | ||||
| CFLAGS_REMOVE_core.o	= -pg | ||||
| KASAN_SANITIZE_core.o	:= n | ||||
| CFLAGS_core.o		+= -fno-stack-protector | ||||
| 
 | ||||
| obj-y += core.o | ||||
| @ -9,18 +9,16 @@ | ||||
| 
 | ||||
| #include <linux/export.h> | ||||
| #include <linux/cc_platform.h> | ||||
| #include <linux/mem_encrypt.h> | ||||
| 
 | ||||
| #include <asm/mshyperv.h> | ||||
| #include <asm/coco.h> | ||||
| #include <asm/processor.h> | ||||
| 
 | ||||
| static bool __maybe_unused intel_cc_platform_has(enum cc_attr attr) | ||||
| static enum cc_vendor vendor __ro_after_init; | ||||
| static u64 cc_mask __ro_after_init; | ||||
| 
 | ||||
| static bool intel_cc_platform_has(enum cc_attr attr) | ||||
| { | ||||
| #ifdef CONFIG_INTEL_TDX_GUEST | ||||
| 	return false; | ||||
| #else | ||||
| 	return false; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -74,12 +72,46 @@ static bool hyperv_cc_platform_has(enum cc_attr attr) | ||||
| 
 | ||||
| bool cc_platform_has(enum cc_attr attr) | ||||
| { | ||||
| 	if (sme_me_mask) | ||||
| 	switch (vendor) { | ||||
| 	case CC_VENDOR_AMD: | ||||
| 		return amd_cc_platform_has(attr); | ||||
| 
 | ||||
| 	if (hv_is_isolation_supported()) | ||||
| 	case CC_VENDOR_INTEL: | ||||
| 		return intel_cc_platform_has(attr); | ||||
| 	case CC_VENDOR_HYPERV: | ||||
| 		return hyperv_cc_platform_has(attr); | ||||
| 
 | ||||
| 	return false; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(cc_platform_has); | ||||
| 
 | ||||
| u64 cc_mkenc(u64 val) | ||||
| { | ||||
| 	switch (vendor) { | ||||
| 	case CC_VENDOR_AMD: | ||||
| 		return val | cc_mask; | ||||
| 	default: | ||||
| 		return val; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| u64 cc_mkdec(u64 val) | ||||
| { | ||||
| 	switch (vendor) { | ||||
| 	case CC_VENDOR_AMD: | ||||
| 		return val & ~cc_mask; | ||||
| 	default: | ||||
| 		return val; | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(cc_mkdec); | ||||
| 
 | ||||
| __init void cc_set_vendor(enum cc_vendor v) | ||||
| { | ||||
| 	vendor = v; | ||||
| } | ||||
| 
 | ||||
| __init void cc_set_mask(u64 mask) | ||||
| { | ||||
| 	cc_mask = mask; | ||||
| } | ||||
							
								
								
									
										32
									
								
								arch/x86/include/asm/coco.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								arch/x86/include/asm/coco.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| #ifndef _ASM_X86_COCO_H | ||||
| #define _ASM_X86_COCO_H | ||||
| 
 | ||||
| #include <asm/types.h> | ||||
| 
 | ||||
| enum cc_vendor { | ||||
| 	CC_VENDOR_NONE, | ||||
| 	CC_VENDOR_AMD, | ||||
| 	CC_VENDOR_HYPERV, | ||||
| 	CC_VENDOR_INTEL, | ||||
| }; | ||||
| 
 | ||||
| void cc_set_vendor(enum cc_vendor v); | ||||
| void cc_set_mask(u64 mask); | ||||
| 
 | ||||
| #ifdef CONFIG_ARCH_HAS_CC_PLATFORM | ||||
| u64 cc_mkenc(u64 val); | ||||
| u64 cc_mkdec(u64 val); | ||||
| #else | ||||
| static inline u64 cc_mkenc(u64 val) | ||||
| { | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| static inline u64 cc_mkdec(u64 val) | ||||
| { | ||||
| 	return val; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* _ASM_X86_COCO_H */ | ||||
| @ -15,17 +15,12 @@ | ||||
| 		     cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS)))	\ | ||||
| 	 : (prot)) | ||||
| 
 | ||||
| /*
 | ||||
|  * Macros to add or remove encryption attribute | ||||
|  */ | ||||
| #define pgprot_encrypted(prot)	__pgprot(__sme_set(pgprot_val(prot))) | ||||
| #define pgprot_decrypted(prot)	__pgprot(__sme_clr(pgprot_val(prot))) | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
| #include <linux/spinlock.h> | ||||
| #include <asm/x86_init.h> | ||||
| #include <asm/pkru.h> | ||||
| #include <asm/fpu/api.h> | ||||
| #include <asm/coco.h> | ||||
| #include <asm-generic/pgtable_uffd.h> | ||||
| #include <linux/page_table_check.h> | ||||
| 
 | ||||
| @ -38,6 +33,12 @@ void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm, | ||||
| void ptdump_walk_pgd_level_checkwx(void); | ||||
| void ptdump_walk_user_pgd_level_checkwx(void); | ||||
| 
 | ||||
| /*
 | ||||
|  * Macros to add or remove encryption attribute | ||||
|  */ | ||||
| #define pgprot_encrypted(prot)	__pgprot(cc_mkenc(pgprot_val(prot))) | ||||
| #define pgprot_decrypted(prot)	__pgprot(cc_mkdec(pgprot_val(prot))) | ||||
| 
 | ||||
| #ifdef CONFIG_DEBUG_WX | ||||
| #define debug_checkwx()		ptdump_walk_pgd_level_checkwx() | ||||
| #define debug_checkwx_user()	ptdump_walk_user_pgd_level_checkwx() | ||||
|  | ||||
| @ -84,7 +84,6 @@ int set_pages_rw(struct page *page, int numpages); | ||||
| int set_direct_map_invalid_noflush(struct page *page); | ||||
| int set_direct_map_default_noflush(struct page *page); | ||||
| bool kernel_page_present(struct page *page); | ||||
| void notify_range_enc_status_changed(unsigned long vaddr, int npages, bool enc); | ||||
| 
 | ||||
| extern int kernel_set_to_readonly; | ||||
| 
 | ||||
|  | ||||
| @ -141,6 +141,21 @@ struct x86_init_acpi { | ||||
| 	void (*reduced_hw_early_init)(void); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct x86_guest - Functions used by misc guest incarnations like SEV, TDX, etc. | ||||
|  * | ||||
|  * @enc_status_change_prepare	Notify HV before the encryption status of a range is changed | ||||
|  * @enc_status_change_finish	Notify HV after the encryption status of a range is changed | ||||
|  * @enc_tlb_flush_required	Returns true if a TLB flush is needed before changing page encryption status | ||||
|  * @enc_cache_flush_required	Returns true if a cache flush is needed before changing page encryption status | ||||
|  */ | ||||
| struct x86_guest { | ||||
| 	void (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc); | ||||
| 	bool (*enc_status_change_finish)(unsigned long vaddr, int npages, bool enc); | ||||
| 	bool (*enc_tlb_flush_required)(bool enc); | ||||
| 	bool (*enc_cache_flush_required)(void); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct x86_init_ops - functions for platform specific setup | ||||
|  * | ||||
| @ -287,6 +302,7 @@ struct x86_platform_ops { | ||||
| 	struct x86_legacy_features legacy; | ||||
| 	void (*set_legacy_features)(void); | ||||
| 	struct x86_hyper_runtime hyper; | ||||
| 	struct x86_guest guest; | ||||
| }; | ||||
| 
 | ||||
| struct x86_apic_ops { | ||||
|  | ||||
| @ -21,7 +21,6 @@ CFLAGS_REMOVE_ftrace.o = -pg | ||||
| CFLAGS_REMOVE_early_printk.o = -pg | ||||
| CFLAGS_REMOVE_head64.o = -pg | ||||
| CFLAGS_REMOVE_sev.o = -pg | ||||
| CFLAGS_REMOVE_cc_platform.o = -pg | ||||
| endif | ||||
| 
 | ||||
| KASAN_SANITIZE_head$(BITS).o				:= n | ||||
| @ -30,7 +29,6 @@ KASAN_SANITIZE_dumpstack_$(BITS).o			:= n | ||||
| KASAN_SANITIZE_stacktrace.o				:= n | ||||
| KASAN_SANITIZE_paravirt.o				:= n | ||||
| KASAN_SANITIZE_sev.o					:= n | ||||
| KASAN_SANITIZE_cc_platform.o				:= n | ||||
| 
 | ||||
| # With some compiler versions the generated code results in boot hangs, caused
 | ||||
| # by several compilation units. To be safe, disable all instrumentation.
 | ||||
| @ -49,7 +47,6 @@ endif | ||||
| KCOV_INSTRUMENT		:= n | ||||
| 
 | ||||
| CFLAGS_head$(BITS).o	+= -fno-stack-protector | ||||
| CFLAGS_cc_platform.o	+= -fno-stack-protector | ||||
| 
 | ||||
| CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace | ||||
| 
 | ||||
| @ -151,8 +148,6 @@ obj-$(CONFIG_UNWINDER_GUESS)		+= unwind_guess.o | ||||
| 
 | ||||
| obj-$(CONFIG_AMD_MEM_ENCRYPT)		+= sev.o | ||||
| 
 | ||||
| obj-$(CONFIG_ARCH_HAS_CC_PLATFORM)	+= cc_platform.o | ||||
| 
 | ||||
| ###
 | ||||
| # 64 bit specific files
 | ||||
| ifeq ($(CONFIG_X86_64),y) | ||||
|  | ||||
| @ -33,6 +33,7 @@ | ||||
| #include <asm/nmi.h> | ||||
| #include <clocksource/hyperv_timer.h> | ||||
| #include <asm/numa.h> | ||||
| #include <asm/coco.h> | ||||
| 
 | ||||
| /* Is Linux running as the root partition? */ | ||||
| bool hv_root_partition; | ||||
| @ -344,6 +345,11 @@ static void __init ms_hyperv_init_platform(void) | ||||
| 		 */ | ||||
| 		swiotlb_force = SWIOTLB_FORCE; | ||||
| #endif | ||||
| 		/* Isolation VMs are unenlightened SEV-based VMs, thus this check: */ | ||||
| 		if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) { | ||||
| 			if (hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE) | ||||
| 				cc_set_vendor(CC_VENDOR_HYPERV); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { | ||||
|  | ||||
| @ -129,6 +129,11 @@ struct x86_cpuinit_ops x86_cpuinit = { | ||||
| 
 | ||||
| static void default_nmi_init(void) { }; | ||||
| 
 | ||||
| static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { } | ||||
| static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; } | ||||
| static bool enc_tlb_flush_required_noop(bool enc) { return false; } | ||||
| static bool enc_cache_flush_required_noop(void) { return false; } | ||||
| 
 | ||||
| struct x86_platform_ops x86_platform __ro_after_init = { | ||||
| 	.calibrate_cpu			= native_calibrate_cpu_early, | ||||
| 	.calibrate_tsc			= native_calibrate_tsc, | ||||
| @ -138,9 +143,16 @@ struct x86_platform_ops x86_platform __ro_after_init = { | ||||
| 	.is_untracked_pat_range		= is_ISA_range, | ||||
| 	.nmi_init			= default_nmi_init, | ||||
| 	.get_nmi_reason			= default_get_nmi_reason, | ||||
| 	.save_sched_clock_state 	= tsc_save_sched_clock_state, | ||||
| 	.restore_sched_clock_state 	= tsc_restore_sched_clock_state, | ||||
| 	.save_sched_clock_state		= tsc_save_sched_clock_state, | ||||
| 	.restore_sched_clock_state	= tsc_restore_sched_clock_state, | ||||
| 	.hyper.pin_vcpu			= x86_op_int_noop, | ||||
| 
 | ||||
| 	.guest = { | ||||
| 		.enc_status_change_prepare = enc_status_change_prepare_noop, | ||||
| 		.enc_status_change_finish  = enc_status_change_finish_noop, | ||||
| 		.enc_tlb_flush_required	   = enc_tlb_flush_required_noop, | ||||
| 		.enc_cache_flush_required  = enc_cache_flush_required_noop, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| EXPORT_SYMBOL_GPL(x86_platform); | ||||
|  | ||||
| @ -177,25 +177,6 @@ void __init sme_map_bootdata(char *real_mode_data) | ||||
| 	__sme_early_map_unmap_mem(__va(cmdline_paddr), COMMAND_LINE_SIZE, true); | ||||
| } | ||||
| 
 | ||||
| void __init sme_early_init(void) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	if (!sme_me_mask) | ||||
| 		return; | ||||
| 
 | ||||
| 	early_pmd_flags = __sme_set(early_pmd_flags); | ||||
| 
 | ||||
| 	__supported_pte_mask = __sme_set(__supported_pte_mask); | ||||
| 
 | ||||
| 	/* Update the protection map with memory encryption mask */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(protection_map); i++) | ||||
| 		protection_map[i] = pgprot_encrypted(protection_map[i]); | ||||
| 
 | ||||
| 	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | ||||
| 		swiotlb_force = SWIOTLB_FORCE; | ||||
| } | ||||
| 
 | ||||
| void __init sev_setup_arch(void) | ||||
| { | ||||
| 	phys_addr_t total_mem = memblock_phys_mem_size(); | ||||
| @ -256,7 +237,17 @@ static unsigned long pg_level_to_pfn(int level, pte_t *kpte, pgprot_t *ret_prot) | ||||
| 	return pfn; | ||||
| } | ||||
| 
 | ||||
| void notify_range_enc_status_changed(unsigned long vaddr, int npages, bool enc) | ||||
| static bool amd_enc_tlb_flush_required(bool enc) | ||||
| { | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool amd_enc_cache_flush_required(void) | ||||
| { | ||||
| 	return !cpu_feature_enabled(X86_FEATURE_SME_COHERENT); | ||||
| } | ||||
| 
 | ||||
| static void enc_dec_hypercall(unsigned long vaddr, int npages, bool enc) | ||||
| { | ||||
| #ifdef CONFIG_PARAVIRT | ||||
| 	unsigned long sz = npages << PAGE_SHIFT; | ||||
| @ -287,6 +278,19 @@ void notify_range_enc_status_changed(unsigned long vaddr, int npages, bool enc) | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static void amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| /* Return true unconditionally: return value doesn't matter for the SEV side */ | ||||
| static bool amd_enc_status_change_finish(unsigned long vaddr, int npages, bool enc) | ||||
| { | ||||
| 	if (!cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)) | ||||
| 		enc_dec_hypercall(vaddr, npages, enc); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc) | ||||
| { | ||||
| 	pgprot_t old_prot, new_prot; | ||||
| @ -392,7 +396,7 @@ static int __init early_set_memory_enc_dec(unsigned long vaddr, | ||||
| 
 | ||||
| 	ret = 0; | ||||
| 
 | ||||
| 	notify_range_enc_status_changed(start, PAGE_ALIGN(size) >> PAGE_SHIFT, enc); | ||||
| 	early_set_mem_enc_dec_hypercall(start, PAGE_ALIGN(size) >> PAGE_SHIFT, enc); | ||||
| out: | ||||
| 	__flush_tlb_all(); | ||||
| 	return ret; | ||||
| @ -410,7 +414,31 @@ int __init early_set_memory_encrypted(unsigned long vaddr, unsigned long size) | ||||
| 
 | ||||
| void __init early_set_mem_enc_dec_hypercall(unsigned long vaddr, int npages, bool enc) | ||||
| { | ||||
| 	notify_range_enc_status_changed(vaddr, npages, enc); | ||||
| 	enc_dec_hypercall(vaddr, npages, enc); | ||||
| } | ||||
| 
 | ||||
| void __init sme_early_init(void) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	if (!sme_me_mask) | ||||
| 		return; | ||||
| 
 | ||||
| 	early_pmd_flags = __sme_set(early_pmd_flags); | ||||
| 
 | ||||
| 	__supported_pte_mask = __sme_set(__supported_pte_mask); | ||||
| 
 | ||||
| 	/* Update the protection map with memory encryption mask */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(protection_map); i++) | ||||
| 		protection_map[i] = pgprot_encrypted(protection_map[i]); | ||||
| 
 | ||||
| 	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | ||||
| 		swiotlb_force = SWIOTLB_FORCE; | ||||
| 
 | ||||
| 	x86_platform.guest.enc_status_change_prepare = amd_enc_status_change_prepare; | ||||
| 	x86_platform.guest.enc_status_change_finish  = amd_enc_status_change_finish; | ||||
| 	x86_platform.guest.enc_tlb_flush_required    = amd_enc_tlb_flush_required; | ||||
| 	x86_platform.guest.enc_cache_flush_required  = amd_enc_cache_flush_required; | ||||
| } | ||||
| 
 | ||||
| void __init mem_encrypt_free_decrypted_mem(void) | ||||
|  | ||||
| @ -44,6 +44,7 @@ | ||||
| #include <asm/setup.h> | ||||
| #include <asm/sections.h> | ||||
| #include <asm/cmdline.h> | ||||
| #include <asm/coco.h> | ||||
| 
 | ||||
| #include "mm_internal.h" | ||||
| 
 | ||||
| @ -565,8 +566,7 @@ void __init sme_enable(struct boot_params *bp) | ||||
| 	} else { | ||||
| 		/* SEV state cannot be controlled by a command line option */ | ||||
| 		sme_me_mask = me_mask; | ||||
| 		physical_mask &= ~sme_me_mask; | ||||
| 		return; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -600,6 +600,10 @@ void __init sme_enable(struct boot_params *bp) | ||||
| 		sme_me_mask = 0; | ||||
| 	else | ||||
| 		sme_me_mask = active_by_default ? me_mask : 0; | ||||
| 
 | ||||
| 	physical_mask &= ~sme_me_mask; | ||||
| out: | ||||
| 	if (sme_me_mask) { | ||||
| 		physical_mask &= ~sme_me_mask; | ||||
| 		cc_set_vendor(CC_VENDOR_AMD); | ||||
| 		cc_set_mask(sme_me_mask); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1989,6 +1989,7 @@ int set_memory_global(unsigned long addr, int numpages) | ||||
|  */ | ||||
| static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) | ||||
| { | ||||
| 	pgprot_t empty = __pgprot(0); | ||||
| 	struct cpa_data cpa; | ||||
| 	int ret; | ||||
| 
 | ||||
| @ -1999,18 +2000,20 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) | ||||
| 	memset(&cpa, 0, sizeof(cpa)); | ||||
| 	cpa.vaddr = &addr; | ||||
| 	cpa.numpages = numpages; | ||||
| 	cpa.mask_set = enc ? __pgprot(_PAGE_ENC) : __pgprot(0); | ||||
| 	cpa.mask_clr = enc ? __pgprot(0) : __pgprot(_PAGE_ENC); | ||||
| 	cpa.mask_set = enc ? pgprot_encrypted(empty) : pgprot_decrypted(empty); | ||||
| 	cpa.mask_clr = enc ? pgprot_decrypted(empty) : pgprot_encrypted(empty); | ||||
| 	cpa.pgd = init_mm.pgd; | ||||
| 
 | ||||
| 	/* Must avoid aliasing mappings in the highmem code */ | ||||
| 	kmap_flush_unused(); | ||||
| 	vm_unmap_aliases(); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Before changing the encryption attribute, we need to flush caches. | ||||
| 	 */ | ||||
| 	cpa_flush(&cpa, !this_cpu_has(X86_FEATURE_SME_COHERENT)); | ||||
| 	/* Flush the caches as needed before changing the encryption attribute. */ | ||||
| 	if (x86_platform.guest.enc_tlb_flush_required(enc)) | ||||
| 		cpa_flush(&cpa, x86_platform.guest.enc_cache_flush_required()); | ||||
| 
 | ||||
| 	/* Notify hypervisor that we are about to set/clr encryption attribute. */ | ||||
| 	x86_platform.guest.enc_status_change_prepare(addr, numpages, enc); | ||||
| 
 | ||||
| 	ret = __change_page_attr_set_clr(&cpa, 1); | ||||
| 
 | ||||
| @ -2023,11 +2026,11 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) | ||||
| 	 */ | ||||
| 	cpa_flush(&cpa, 0); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Notify hypervisor that a given memory range is mapped encrypted | ||||
| 	 * or decrypted. | ||||
| 	 */ | ||||
| 	notify_range_enc_status_changed(addr, numpages, enc); | ||||
| 	/* Notify hypervisor that we have successfully set/clr encryption attribute. */ | ||||
| 	if (!ret) { | ||||
| 		if (!x86_platform.guest.enc_status_change_finish(addr, numpages, enc)) | ||||
| 			ret = -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user