Skip to content

Commit

Permalink
x86/sev: Use CC_ATTR attribute to generalize string I/O unroll
Browse files Browse the repository at this point in the history
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: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Tested-by: Tom Lendacky <thomas.lendacky@amd.com>
Link: https://lkml.kernel.org/r/20211206135505.75045-2-kirill.shutemov@linux.intel.com
  • Loading branch information
Kuppuswamy Sathyanarayanan authored and Borislav Petkov committed Dec 8, 2021
1 parent 75cc9a8 commit 8260b98
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 27 deletions.
20 changes: 3 additions & 17 deletions arch/x86/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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) \
{ \
Expand Down Expand Up @@ -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); \
Expand All @@ -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); \
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/kernel/cc_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
10 changes: 0 additions & 10 deletions arch/x86/mm/mem_encrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
}

Expand Down
11 changes: 11 additions & 0 deletions include/linux/cc_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 8260b98

Please sign in to comment.