Commit 8260b982 authored by Kuppuswamy Sathyanarayanan's avatar Kuppuswamy Sathyanarayanan Committed by Borislav Petkov
Browse files

x86/sev: Use CC_ATTR attribute to generalize string I/O unroll



INS/OUTS are not supported in TDX guests and cause #UD. Kernel has to
avoid them when running in TDX guest. To support existing usage, string
I/O operations are unrolled using IN/OUT instructions.

AMD SEV platform implements this support by adding unroll
logic in ins#bwl()/outs#bwl() macros with SEV-specific checks.
Since TDX VM guests will also need similar support, use
CC_ATTR_GUEST_UNROLL_STRING_IO and generic cc_platform_has() API to
implement it.

String I/O helpers were the last users of sev_key_active() interface and
sev_enable_key static key. Remove them.

 [ bp: Move comment too and do not delete it. ]

Suggested-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarTony Luck <tony.luck@intel.com>
Reviewed-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Tested-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Link: https://lkml.kernel.org/r/20211206135505.75045-2-kirill.shutemov@linux.intel.com
parent 75cc9a84
Loading
Loading
Loading
Loading
+3 −17
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@

#include <linux/string.h>
#include <linux/compiler.h>
#include <linux/cc_platform.h>
#include <asm/page.h>
#include <asm/early_ioremap.h>
#include <asm/pgtable_types.h>
@@ -256,21 +257,6 @@ static inline void slow_down_io(void)

#endif

#ifdef CONFIG_AMD_MEM_ENCRYPT
#include <linux/jump_label.h>

extern struct static_key_false sev_enable_key;
static inline bool sev_key_active(void)
{
	return static_branch_unlikely(&sev_enable_key);
}

#else /* !CONFIG_AMD_MEM_ENCRYPT */

static inline bool sev_key_active(void) { return false; }

#endif /* CONFIG_AMD_MEM_ENCRYPT */

#define BUILDIO(bwl, bw, type)						\
static inline void out##bwl(unsigned type value, int port)		\
{									\
@@ -301,7 +287,7 @@ static inline unsigned type in##bwl##_p(int port) \
									\
static inline void outs##bwl(int port, const void *addr, unsigned long count) \
{									\
	if (sev_key_active()) {						\
	if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) {		\
		unsigned type *value = (unsigned type *)addr;		\
		while (count) {						\
			out##bwl(*value, port);				\
@@ -317,7 +303,7 @@ static inline void outs##bwl(int port, const void *addr, unsigned long count) \
									\
static inline void ins##bwl(int port, void *addr, unsigned long count)	\
{									\
	if (sev_key_active()) {						\
	if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) {		\
		unsigned type *value = (unsigned type *)addr;		\
		while (count) {						\
			*value = in##bwl(port);				\
+8 −0
Original line number Diff line number Diff line
@@ -50,6 +50,14 @@ static bool amd_cc_platform_has(enum cc_attr attr)
	case CC_ATTR_GUEST_STATE_ENCRYPT:
		return sev_status & MSR_AMD64_SEV_ES_ENABLED;

	/*
	 * With SEV, the rep string I/O instructions need to be unrolled
	 * but SEV-ES supports them through the #VC handler.
	 */
	case CC_ATTR_GUEST_UNROLL_STRING_IO:
		return (sev_status & MSR_AMD64_SEV_ENABLED) &&
			!(sev_status & MSR_AMD64_SEV_ES_ENABLED);

	default:
		return false;
	}
+0 −10
Original line number Diff line number Diff line
@@ -43,8 +43,6 @@ u64 sme_me_mask __section(".data") = 0;
u64 sev_status __section(".data") = 0;
u64 sev_check_data __section(".data") = 0;
EXPORT_SYMBOL(sme_me_mask);
DEFINE_STATIC_KEY_FALSE(sev_enable_key);
EXPORT_SYMBOL_GPL(sev_enable_key);

/* Buffer used for early in-place encryption by BSP, no locking needed */
static char sme_early_buffer[PAGE_SIZE] __initdata __aligned(PAGE_SIZE);
@@ -499,14 +497,6 @@ void __init mem_encrypt_init(void)
	/* Call into SWIOTLB to update the SWIOTLB DMA buffers */
	swiotlb_update_mem_attributes();

	/*
	 * With SEV, we need to unroll the rep string I/O instructions,
	 * but SEV-ES supports them through the #VC handler.
	 */
	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) &&
	    !cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
		static_branch_enable(&sev_enable_key);

	print_mem_encrypt_feature_info();
}

+11 −0
Original line number Diff line number Diff line
@@ -61,6 +61,17 @@ enum cc_attr {
	 * Examples include SEV-ES.
	 */
	CC_ATTR_GUEST_STATE_ENCRYPT,

	/**
	 * @CC_ATTR_GUEST_UNROLL_STRING_IO: String I/O is implemented with
	 *                                  IN/OUT instructions
	 *
	 * The platform/OS is running as a guest/virtual machine and uses
	 * IN/OUT instructions in place of string I/O.
	 *
	 * Examples include TDX guest & SEV.
	 */
	CC_ATTR_GUEST_UNROLL_STRING_IO,
};

#ifdef CONFIG_ARCH_HAS_CC_PLATFORM