linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD)
@ 2017-09-27 15:13 Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 01/17] Documentation/x86: Add AMD Secure Encrypted Virtualization (SEV) description Brijesh Singh
                   ` (17 more replies)
  0 siblings, 18 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Tom Lendacky, Paolo Bonzini,
	Radim Krčmář

This part of Secure Encrypted Virtualization (SEV) series focuses on the
changes required in a guest OS for SEV support.

When SEV is active, the memory content of guest OS will be transparently encrypted
with a key unique to the guest VM.

SEV guests have concept of private and shared memory. Private memory is encrypted
with the guest-specific key, while shared memory may be encrypted with hypervisor
key. Certain type of memory (namely insruction pages and guest page tables) are
always treated as private. Due to security reasons all DMA operations inside the
guest must be performed on shared memory.

The SEV feature is enabled by the hypervisor, and guest can identify it through
CPUID function and the 0xc0010131 (F17H_SEV) MSR. When enabled, page table entries
will determine how memory is accessed. If a page table entry has the memory
encryption mask set, then that memory will be accessed using guest-specific key.
Certain memory (instruction pages, page tables) will always be accessed using
guest-specific key.

This patch series builds upon the Secure Memory Encryption (SME) feature. Unlike
SME, when SEV is enabled, all the data (e.g EFI, kernel, initrd, etc) will have
been placed into memory as encrypted by the guest BIOS.

The approach that this patch series takes is to encrypt everything possible
starting early in the boot. Since the DMA operations inside guest must be
performed on shared memory hence it uses SW-IOTLB to complete the DMA operations.

The following links provide additional details:

AMD Memory Encryption whitepaper:
http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
    http://support.amd.com/TechDocs/24593.pdf
    SME is section 7.10
    SEV is section 15.34

Secure Encrypted Virutualization Key Management:
http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf

KVM Forum Presentation:
http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf

SEV Guest BIOS support:
  SEV support has been accepted into EDKII/OVMF BIOS
  https://github.com/tianocore/edk2/commits/master

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org

---
This series is based on tip/master commit : a35205980288 (Merge branch 'WIP.x86/fpu').

Complete git tree is available: https://github.com/codomania/tip/tree/sev-v5-p1

Changes since v4:
 * rename per-CPU define to DEFINE_PER_CPU_DECRYPTED
 * add more comments in per-CPU section definition
 * rename __sev_active() to sev_key_active() to use more obivious naming
 * changes to address v4 feedbacks

Changes since v3:
 * use static key to branch the unrolling of rep ins/outs when SEV is active
 * simplify the memory encryption detection logic
 * rename per-cpu define to DEFINE_PER_CPU_UNENCRYPTED
 * simplfy the logic to map per-cpu as unencrypted
 * changes to address v3 feedbacks

Changes since v2:
 * add documentation
 * update early_set_memory_* to use kernel_physical_mapping_init()
   to split larger page into smaller (recommended by Boris)
 * changes to address v2 feedback
 * drop hypervisor specific patches, those patches will be included in part 2

Brijesh Singh (5):
  Documentation/x86: Add AMD Secure Encrypted Virtualization (SEV)
    description
  x86: Add support for changing memory encryption attribute in early
    boot
  percpu: Introduce DEFINE_PER_CPU_DECRYPTED
  X86/KVM: Decrypt shared per-cpu variables when SEV is active
  X86/KVM: Clear encryption attribute when SEV is active

Tom Lendacky (12):
  x86/mm: Add Secure Encrypted Virtualization (SEV) support
  x86/mm: Don't attempt to encrypt initrd under SEV
  x86/realmode: Don't decrypt trampoline area under SEV
  x86/mm: Use encrypted access of boot related data with SEV
  x86/mm: Include SEV for encryption memory attribute changes
  x86/efi: Access EFI data as encrypted when SEV is active
  resource: Consolidate resource walking code
  resource: Provide resource struct in resource walk callback
  x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory
    pages
  x86/mm: Add DMA support for SEV memory encryption
  x86/boot: Add early boot support when running with SEV active
  x86/io: Unroll string I/O when SEV is active

 Documentation/x86/amd-memory-encryption.txt |  30 ++-
 arch/powerpc/kernel/machine_kexec_file_64.c |  12 +-
 arch/x86/boot/compressed/Makefile           |   1 +
 arch/x86/boot/compressed/head_64.S          |  16 ++
 arch/x86/boot/compressed/mem_encrypt.S      | 120 ++++++++++++
 arch/x86/boot/compressed/misc.h             |   2 +
 arch/x86/boot/compressed/pagetable.c        |   8 +-
 arch/x86/entry/vdso/vma.c                   |   5 +-
 arch/x86/include/asm/io.h                   |  42 +++-
 arch/x86/include/asm/mem_encrypt.h          |  14 ++
 arch/x86/include/asm/msr-index.h            |   3 +
 arch/x86/include/uapi/asm/kvm_para.h        |   1 -
 arch/x86/kernel/crash.c                     |  18 +-
 arch/x86/kernel/kvm.c                       |  41 +++-
 arch/x86/kernel/kvmclock.c                  |  65 +++++--
 arch/x86/kernel/pmem.c                      |   2 +-
 arch/x86/kernel/setup.c                     |   6 +-
 arch/x86/mm/ioremap.c                       | 123 +++++++++---
 arch/x86/mm/mem_encrypt.c                   | 291 ++++++++++++++++++++++++++--
 arch/x86/mm/pageattr.c                      |   4 +-
 arch/x86/platform/efi/efi_64.c              |  16 +-
 arch/x86/realmode/init.c                    |   5 +-
 include/asm-generic/vmlinux.lds.h           |  19 ++
 include/linux/ioport.h                      |   7 +-
 include/linux/kexec.h                       |   2 +-
 include/linux/mem_encrypt.h                 |   7 +-
 include/linux/percpu-defs.h                 |  15 ++
 kernel/kexec_file.c                         |   5 +-
 kernel/resource.c                           |  76 +++++---
 lib/swiotlb.c                               |   5 +-
 30 files changed, 838 insertions(+), 123 deletions(-)
 create mode 100644 arch/x86/boot/compressed/mem_encrypt.S

-- 
2.9.5

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 01/17] Documentation/x86: Add AMD Secure Encrypted Virtualization (SEV) description
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support Brijesh Singh
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jonathan Corbet, Borislav Petkov, Tom Lendacky

Update the AMD memory encryption document describing the Secure Encrypted
Virtualization (SEV) feature.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 Documentation/x86/amd-memory-encryption.txt | 30 +++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
index f512ab718541..afc41f544dab 100644
--- a/Documentation/x86/amd-memory-encryption.txt
+++ b/Documentation/x86/amd-memory-encryption.txt
@@ -1,4 +1,5 @@
-Secure Memory Encryption (SME) is a feature found on AMD processors.
+Secure Memory Encryption (SME) and Secure Encrypted Virtualization (SEV) are
+features found on AMD processors.
 
 SME provides the ability to mark individual pages of memory as encrypted using
 the standard x86 page tables.  A page that is marked encrypted will be
@@ -6,24 +7,38 @@ automatically decrypted when read from DRAM and encrypted when written to
 DRAM.  SME can therefore be used to protect the contents of DRAM from physical
 attacks on the system.
 
+SEV enables running encrypted virtual machines (VMs) in which the code and data
+of the guest VM are secured so that a decrypted version is available only
+within the VM itself. SEV guest VMs have the concept of private and shared
+memory. Private memory is encrypted with the guest-specific key, while shared
+memory may be encrypted with hypervisor key. When SME is enabled, the hypervisor
+key is the same key which is used in SME.
+
 A page is encrypted when a page table entry has the encryption bit set (see
 below on how to determine its position).  The encryption bit can also be
 specified in the cr3 register, allowing the PGD table to be encrypted. Each
 successive level of page tables can also be encrypted by setting the encryption
 bit in the page table entry that points to the next table. This allows the full
 page table hierarchy to be encrypted. Note, this means that just because the
-encryption bit is set in cr3, doesn't imply the full hierarchy is encyrpted.
+encryption bit is set in cr3, doesn't imply the full hierarchy is encrypted.
 Each page table entry in the hierarchy needs to have the encryption bit set to
 achieve that. So, theoretically, you could have the encryption bit set in cr3
 so that the PGD is encrypted, but not set the encryption bit in the PGD entry
 for a PUD which results in the PUD pointed to by that entry to not be
 encrypted.
 
-Support for SME can be determined through the CPUID instruction. The CPUID
-function 0x8000001f reports information related to SME:
+When SEV is enabled, instruction pages and guest page tables are always treated
+as private. All the DMA operations inside the guest must be performed on shared
+memory. Since the memory encryption bit is controlled by the guest OS when it
+is operating in 64-bit or 32-bit PAE mode, in all other modes the SEV hardware
+forces the memory encryption bit to 1.
+
+Support for SME and SEV can be determined through the CPUID instruction. The
+CPUID function 0x8000001f reports information related to SME:
 
 	0x8000001f[eax]:
 		Bit[0] indicates support for SME
+		Bit[1] indicates support for SEV
 	0x8000001f[ebx]:
 		Bits[5:0]  pagetable bit number used to activate memory
 			   encryption
@@ -39,6 +54,13 @@ determine if SME is enabled and/or to enable memory encryption:
 		Bit[23]   0 = memory encryption features are disabled
 			  1 = memory encryption features are enabled
 
+If SEV is supported, MSR 0xc0010131 (MSR_AMD64_SEV) can be used to determine if
+SEV is active:
+
+	0xc0010131:
+		Bit[0]	  0 = memory encryption is not active
+			  1 = memory encryption is active
+
 Linux relies on BIOS to set this bit if BIOS has determined that the reduction
 in the physical address space as a result of enabling memory encryption (see
 CPUID information above) will not conflict with the address space resource
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 01/17] Documentation/x86: Add AMD Secure Encrypted Virtualization (SEV) description Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-28  9:02   ` Borislav Petkov
  2017-09-27 15:13 ` [Part1 PATCH v5 03/17] x86/mm: Don't attempt to encrypt initrd under SEV Brijesh Singh
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

Provide support for Secure Encrypted Virtualization (SEV). This initial
support defines a flag that is used by the kernel to determine if it is
running with SEV active.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |  6 ++++++
 arch/x86/mm/mem_encrypt.c          | 26 ++++++++++++++++++++++++++
 include/linux/mem_encrypt.h        |  7 +++++--
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 6a77c63540f7..2b024741bce9 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -47,6 +47,9 @@ void __init mem_encrypt_init(void);
 
 void swiotlb_set_mem_attributes(void *vaddr, unsigned long size);
 
+bool sme_active(void);
+bool sev_active(void);
+
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask	0ULL
@@ -64,6 +67,9 @@ static inline void __init sme_early_init(void) { }
 static inline void __init sme_encrypt_kernel(void) { }
 static inline void __init sme_enable(struct boot_params *bp) { }
 
+static inline bool sme_active(void) { return false; }
+static inline bool sev_active(void) { return false; }
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 /*
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 3fcc8e01683b..5ad6ea61bd1a 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -40,6 +40,8 @@ static char sme_cmdline_off[] __initdata = "off";
 u64 sme_me_mask __section(.data) = 0;
 EXPORT_SYMBOL_GPL(sme_me_mask);
 
+static bool sev_enabled;
+
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
@@ -190,6 +192,30 @@ void __init sme_early_init(void)
 		protection_map[i] = pgprot_encrypted(protection_map[i]);
 }
 
+/*
+ * SME and SEV are very similar but they are not the same, so there are
+ * times that the kernel will need to distinguish between SME and SEV. The
+ * sme_active() and sev_active() functions are used for this.  When a
+ * distinction isn't needed, the mem_encrypt_active() function can be used.
+ *
+ * The trampoline code is a good example for this requirement.  Before
+ * paging is activated, SME will access all memory as decrypted, but SEV
+ * will access all memory as encrypted.  So, when APs are being brought
+ * up under SME the trampoline area cannot be encrypted, whereas under SEV
+ * the trampoline area must be encrypted.
+ */
+bool sme_active(void)
+{
+	return sme_me_mask && !sev_enabled;
+}
+EXPORT_SYMBOL_GPL(sme_active);
+
+bool sev_active(void)
+{
+	return sme_me_mask && sev_enabled;
+}
+EXPORT_SYMBOL_GPL(sev_active);
+
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void)
 {
diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
index 265a9cd21cb4..b310a9c18113 100644
--- a/include/linux/mem_encrypt.h
+++ b/include/linux/mem_encrypt.h
@@ -23,11 +23,14 @@
 
 #define sme_me_mask	0ULL
 
+static inline bool sme_active(void) { return false; }
+static inline bool sev_active(void) { return false; }
+
 #endif	/* CONFIG_ARCH_HAS_MEM_ENCRYPT */
 
-static inline bool sme_active(void)
+static inline bool mem_encrypt_active(void)
 {
-	return !!sme_me_mask;
+	return sme_me_mask;
 }
 
 static inline u64 sme_get_me_mask(void)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 03/17] x86/mm: Don't attempt to encrypt initrd under SEV
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 01/17] Documentation/x86: Add AMD Secure Encrypted Virtualization (SEV) description Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 04/17] x86/realmode: Don't decrypt trampoline area " Brijesh Singh
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

When SEV is active the initrd/initramfs will already have already been
placed in memory encrypted so do not try to encrypt it.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/kernel/setup.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 82559867e0a9..967155e63afe 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -368,9 +368,11 @@ static void __init reserve_initrd(void)
 	 * If SME is active, this memory will be marked encrypted by the
 	 * kernel when it is accessed (including relocation). However, the
 	 * ramdisk image was loaded decrypted by the bootloader, so make
-	 * sure that it is encrypted before accessing it.
+	 * sure that it is encrypted before accessing it. For SEV the
+	 * ramdisk will already be encrypted, so only do this for SME.
 	 */
-	sme_early_encrypt(ramdisk_image, ramdisk_end - ramdisk_image);
+	if (sme_active())
+		sme_early_encrypt(ramdisk_image, ramdisk_end - ramdisk_image);
 
 	initrd_start = 0;
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 04/17] x86/realmode: Don't decrypt trampoline area under SEV
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (2 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 03/17] x86/mm: Don't attempt to encrypt initrd under SEV Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV Brijesh Singh
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Laura Abbott,
	Kirill A. Shutemov, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

When SEV is active the trampoline area will need to be in encrypted
memory so only mark the area decrypted if SME is active.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Laura Abbott <labbott@redhat.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/realmode/init.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 1f71980fc5e0..d03125c2b73b 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -63,9 +63,10 @@ static void __init setup_real_mode(void)
 	/*
 	 * If SME is active, the trampoline area will need to be in
 	 * decrypted memory in order to bring up other processors
-	 * successfully.
+	 * successfully. This is not needed for SEV.
 	 */
-	set_memory_decrypted((unsigned long)base, size >> PAGE_SHIFT);
+	if (sme_active())
+		set_memory_decrypted((unsigned long)base, size >> PAGE_SHIFT);
 
 	memcpy(base, real_mode_blob, size);
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (3 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 04/17] x86/realmode: Don't decrypt trampoline area " Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-28 11:13   ` Borislav Petkov
  2017-09-28 16:20   ` [Part1 PATCH v5.1 " Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes Brijesh Singh
                   ` (12 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Laura Abbott,
	Kirill A. Shutemov, Matt Fleming, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

When Secure Encrypted Virtualization (SEV) is active, boot data (such as
EFI related data, setup data) is encrypted and needs to be accessed as
such when mapped. Update the architecture override in early_memremap to
keep the encryption attribute when mapping this data.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Laura Abbott <labbott@redhat.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/mm/ioremap.c | 44 ++++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 34f0e1847dd6..52cc0f4ed494 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -422,6 +422,9 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
  * areas should be mapped decrypted. And since the encryption key can
  * change across reboots, persistent memory should also be mapped
  * decrypted.
+ *
+ * If SEV is active, that implies that BIOS/UEFI also ran encrypted so
+ * only persistent memory should be mapped decrypted.
  */
 static bool memremap_should_map_decrypted(resource_size_t phys_addr,
 					  unsigned long size)
@@ -458,6 +461,11 @@ static bool memremap_should_map_decrypted(resource_size_t phys_addr,
 	case E820_TYPE_ACPI:
 	case E820_TYPE_NVS:
 	case E820_TYPE_UNUSABLE:
+		/* For SEV, these areas are encrypted */
+		if (sev_active())
+			break;
+		/* Fallthrough */
+
 	case E820_TYPE_PRAM:
 		return true;
 	default:
@@ -581,7 +589,7 @@ static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
 bool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size,
 				 unsigned long flags)
 {
-	if (!sme_active())
+	if (!mem_encrypt_active())
 		return true;
 
 	if (flags & MEMREMAP_ENC)
@@ -590,12 +598,13 @@ bool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size,
 	if (flags & MEMREMAP_DEC)
 		return false;
 
-	if (memremap_is_setup_data(phys_addr, size) ||
-	    memremap_is_efi_data(phys_addr, size) ||
-	    memremap_should_map_decrypted(phys_addr, size))
-		return false;
+	if (sme_active()) {
+		if (memremap_is_setup_data(phys_addr, size) ||
+		    memremap_is_efi_data(phys_addr, size))
+			return false;
+	}
 
-	return true;
+	return !memremap_should_map_decrypted(phys_addr, size);
 }
 
 /*
@@ -608,17 +617,24 @@ pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
 					     unsigned long size,
 					     pgprot_t prot)
 {
-	if (!sme_active())
+	bool encrypted_prot;
+
+	if (!mem_encrypt_active())
 		return prot;
 
-	if (early_memremap_is_setup_data(phys_addr, size) ||
-	    memremap_is_efi_data(phys_addr, size) ||
-	    memremap_should_map_decrypted(phys_addr, size))
-		prot = pgprot_decrypted(prot);
-	else
-		prot = pgprot_encrypted(prot);
+	encrypted_prot = true;
+
+	if (sme_active()) {
+		if (early_memremap_is_setup_data(phys_addr, size) ||
+		    memremap_is_efi_data(phys_addr, size))
+			encrypted_prot = false;
+	}
+
+	if (encrypted_prot && memremap_should_map_decrypted(phys_addr, size))
+		encrypted_prot = false;
 
-	return prot;
+	return encrypted_prot ? pgprot_encrypted(prot)
+			      : pgprot_decrypted(prot);
 }
 
 bool phys_mem_access_encrypted(unsigned long phys_addr, unsigned long size)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (4 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:53   ` Brijesh Singh
  2017-09-27 19:17   ` [Part1 PATCH v5.1 " Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 07/17] x86/efi: Access EFI data as encrypted when SEV is active Brijesh Singh
                   ` (11 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, John Ogness, Matt Fleming,
	Laura Abbott, Dan Williams, Kirill A. Shutemov, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

The current code checks only for sme_active() when determining whether
to perform the encryption attribute change.  Include sev_active() in this
check so that memory attribute changes can occur under SME and SEV.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/mm/pageattr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index dfb7d657cf43..3fe68483463c 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1781,8 +1781,8 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
 	unsigned long start;
 	int ret;
 
-	/* Nothing to do if the SME is not active */
-	if (!sme_active())
+	/* Nothing to do if memory encryption is not active */
+	if (!mem_encrypt_active())
 		return 0;
 
 	/* Should not be working on unaligned addresses */
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 07/17] x86/efi: Access EFI data as encrypted when SEV is active
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (5 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 08/17] resource: Consolidate resource walking code Brijesh Singh
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Matt Fleming, Ard Biesheuvel,
	linux-efi, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

EFI data is encrypted when the kernel is run under SEV. Update the
page table references to be sure the EFI memory areas are accessed
encrypted.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: linux-efi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/platform/efi/efi_64.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 12e83888e5b9..5469c9319f43 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -32,6 +32,7 @@
 #include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/ucs2_string.h>
+#include <linux/mem_encrypt.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
@@ -369,7 +370,11 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	 * as trim_bios_range() will reserve the first page and isolate it away
 	 * from memory allocators anyway.
 	 */
-	if (kernel_map_pages_in_pgd(pgd, 0x0, 0x0, 1, _PAGE_RW)) {
+	pf = _PAGE_RW;
+	if (sev_active())
+		pf |= _PAGE_ENC;
+
+	if (kernel_map_pages_in_pgd(pgd, 0x0, 0x0, 1, pf)) {
 		pr_err("Failed to create 1:1 mapping for the first page!\n");
 		return 1;
 	}
@@ -412,6 +417,9 @@ static void __init __map_region(efi_memory_desc_t *md, u64 va)
 	if (!(md->attribute & EFI_MEMORY_WB))
 		flags |= _PAGE_PCD;
 
+	if (sev_active())
+		flags |= _PAGE_ENC;
+
 	pfn = md->phys_addr >> PAGE_SHIFT;
 	if (kernel_map_pages_in_pgd(pgd, pfn, va, md->num_pages, flags))
 		pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n",
@@ -538,6 +546,9 @@ static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *m
 	if (!(md->attribute & EFI_MEMORY_RO))
 		pf |= _PAGE_RW;
 
+	if (sev_active())
+		pf |= _PAGE_ENC;
+
 	return efi_update_mappings(md, pf);
 }
 
@@ -589,6 +600,9 @@ void __init efi_runtime_update_mappings(void)
 			(md->type != EFI_RUNTIME_SERVICES_CODE))
 			pf |= _PAGE_RW;
 
+		if (sev_active())
+			pf |= _PAGE_ENC;
+
 		efi_update_mappings(md, pf);
 	}
 }
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 08/17] resource: Consolidate resource walking code
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (6 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 07/17] x86/efi: Access EFI data as encrypted when SEV is active Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 09/17] resource: Provide resource struct in resource walk callback Brijesh Singh
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86; +Cc: Tom Lendacky, Borislav Petkov, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

The walk_iomem_res_desc(), walk_system_ram_res() and walk_system_ram_range()
functions each have much of the same code.  Create a new function that
consolidates the common code from these functions in one place to reduce
the amount of duplicated code.

Cc: Borislav Petkov <bp@suse.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 kernel/resource.c | 52 +++++++++++++++++++++++++---------------------------
 1 file changed, 25 insertions(+), 27 deletions(-)

diff --git a/kernel/resource.c b/kernel/resource.c
index 9b5f04404152..7323c1b636cd 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -400,6 +400,26 @@ static int find_next_iomem_res(struct resource *res, unsigned long desc,
 	return 0;
 }
 
+static int __walk_iomem_res_desc(struct resource *res, unsigned long desc,
+				 bool first_level_children_only,
+				 void *arg, int (*func)(u64, u64, void *))
+{
+	u64 orig_end = res->end;
+	int ret = -1;
+
+	while ((res->start < res->end) &&
+	       !find_next_iomem_res(res, desc, first_level_children_only)) {
+		ret = (*func)(res->start, res->end, arg);
+		if (ret)
+			break;
+
+		res->start = res->end + 1;
+		res->end = orig_end;
+	}
+
+	return ret;
+}
+
 /*
  * Walks through iomem resources and calls func() with matching resource
  * ranges. This walks through whole tree and not just first level children.
@@ -418,26 +438,12 @@ int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
 		u64 end, void *arg, int (*func)(u64, u64, void *))
 {
 	struct resource res;
-	u64 orig_end;
-	int ret = -1;
 
 	res.start = start;
 	res.end = end;
 	res.flags = flags;
-	orig_end = res.end;
-
-	while ((res.start < res.end) &&
-		(!find_next_iomem_res(&res, desc, false))) {
-
-		ret = (*func)(res.start, res.end, arg);
-		if (ret)
-			break;
-
-		res.start = res.end + 1;
-		res.end = orig_end;
-	}
 
-	return ret;
+	return __walk_iomem_res_desc(&res, desc, false, arg, func);
 }
 
 /*
@@ -451,22 +457,13 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
 				int (*func)(u64, u64, void *))
 {
 	struct resource res;
-	u64 orig_end;
-	int ret = -1;
 
 	res.start = start;
 	res.end = end;
 	res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
-	orig_end = res.end;
-	while ((res.start < res.end) &&
-		(!find_next_iomem_res(&res, IORES_DESC_NONE, true))) {
-		ret = (*func)(res.start, res.end, arg);
-		if (ret)
-			break;
-		res.start = res.end + 1;
-		res.end = orig_end;
-	}
-	return ret;
+
+	return __walk_iomem_res_desc(&res, IORES_DESC_NONE, true,
+				     arg, func);
 }
 
 #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
@@ -508,6 +505,7 @@ static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
 {
 	return 1;
 }
+
 /*
  * This generic page_is_ram() returns true if specified address is
  * registered as System RAM in iomem_resource list.
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 09/17] resource: Provide resource struct in resource walk callback
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (7 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 08/17] resource: Consolidate resource walking code Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages Brijesh Singh
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, linuxppc-dev, Benjamin Herrenschmidt,
	Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

In prep for a new function that will need additional resource information
during the resource walk, update the resource walk callback to pass the
resource structure.  Since the current callback start and end arguments
are pulled from the resource structure, the callback functions can obtain
them from the resource structure directly.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: linux-kernel@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/powerpc/kernel/machine_kexec_file_64.c | 12 +++++++++---
 arch/x86/kernel/crash.c                     | 18 +++++++++---------
 arch/x86/kernel/pmem.c                      |  2 +-
 include/linux/ioport.h                      |  4 ++--
 include/linux/kexec.h                       |  2 +-
 kernel/kexec_file.c                         |  5 +++--
 kernel/resource.c                           |  9 +++++----
 7 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/kernel/machine_kexec_file_64.c b/arch/powerpc/kernel/machine_kexec_file_64.c
index 992c0d258e5d..e4395f937d63 100644
--- a/arch/powerpc/kernel/machine_kexec_file_64.c
+++ b/arch/powerpc/kernel/machine_kexec_file_64.c
@@ -91,11 +91,13 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
  * and that value will be returned. If all free regions are visited without
  * func returning non-zero, then zero will be returned.
  */
-int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *))
+int arch_kexec_walk_mem(struct kexec_buf *kbuf,
+			int (*func)(struct resource *, void *))
 {
 	int ret = 0;
 	u64 i;
 	phys_addr_t mstart, mend;
+	struct resource res = { };
 
 	if (kbuf->top_down) {
 		for_each_free_mem_range_reverse(i, NUMA_NO_NODE, 0,
@@ -105,7 +107,9 @@ int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *))
 			 * range while in kexec, end points to the last byte
 			 * in the range.
 			 */
-			ret = func(mstart, mend - 1, kbuf);
+			res.start = mstart;
+			res.end = mend - 1;
+			ret = func(&res, kbuf);
 			if (ret)
 				break;
 		}
@@ -117,7 +121,9 @@ int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *))
 			 * range while in kexec, end points to the last byte
 			 * in the range.
 			 */
-			ret = func(mstart, mend - 1, kbuf);
+			res.start = mstart;
+			res.end = mend - 1;
+			ret = func(&res, kbuf);
 			if (ret)
 				break;
 		}
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 44404e2307bb..815008c9ca18 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -209,7 +209,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
 }
 
 #ifdef CONFIG_KEXEC_FILE
-static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg)
+static int get_nr_ram_ranges_callback(struct resource *res, void *arg)
 {
 	unsigned int *nr_ranges = arg;
 
@@ -342,7 +342,7 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
 	return ret;
 }
 
-static int prepare_elf64_ram_headers_callback(u64 start, u64 end, void *arg)
+static int prepare_elf64_ram_headers_callback(struct resource *res, void *arg)
 {
 	struct crash_elf_data *ced = arg;
 	Elf64_Ehdr *ehdr;
@@ -355,7 +355,7 @@ static int prepare_elf64_ram_headers_callback(u64 start, u64 end, void *arg)
 	ehdr = ced->ehdr;
 
 	/* Exclude unwanted mem ranges */
-	ret = elf_header_exclude_ranges(ced, start, end);
+	ret = elf_header_exclude_ranges(ced, res->start, res->end);
 	if (ret)
 		return ret;
 
@@ -518,14 +518,14 @@ static int add_e820_entry(struct boot_params *params, struct e820_entry *entry)
 	return 0;
 }
 
-static int memmap_entry_callback(u64 start, u64 end, void *arg)
+static int memmap_entry_callback(struct resource *res, void *arg)
 {
 	struct crash_memmap_data *cmd = arg;
 	struct boot_params *params = cmd->params;
 	struct e820_entry ei;
 
-	ei.addr = start;
-	ei.size = end - start + 1;
+	ei.addr = res->start;
+	ei.size = res->end - res->start + 1;
 	ei.type = cmd->type;
 	add_e820_entry(params, &ei);
 
@@ -619,12 +619,12 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
 	return ret;
 }
 
-static int determine_backup_region(u64 start, u64 end, void *arg)
+static int determine_backup_region(struct resource *res, void *arg)
 {
 	struct kimage *image = arg;
 
-	image->arch.backup_src_start = start;
-	image->arch.backup_src_sz = end - start + 1;
+	image->arch.backup_src_start = res->start;
+	image->arch.backup_src_sz = res->end - res->start + 1;
 
 	/* Expecting only one range for backup region */
 	return 1;
diff --git a/arch/x86/kernel/pmem.c b/arch/x86/kernel/pmem.c
index 0c5315d322c8..297bb71f10c5 100644
--- a/arch/x86/kernel/pmem.c
+++ b/arch/x86/kernel/pmem.c
@@ -6,7 +6,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 
-static int found(u64 start, u64 end, void *data)
+static int found(struct resource *res, void *data)
 {
 	return 1;
 }
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index f5cf32e80041..617d8a2aac67 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -271,10 +271,10 @@ walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
 		void *arg, int (*func)(unsigned long, unsigned long, void *));
 extern int
 walk_system_ram_res(u64 start, u64 end, void *arg,
-		    int (*func)(u64, u64, void *));
+		    int (*func)(struct resource *, void *));
 extern int
 walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end,
-		    void *arg, int (*func)(u64, u64, void *));
+		    void *arg, int (*func)(struct resource *, void *));
 
 /* True if any part of r1 overlaps r2 */
 static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 2b7590f5483a..d672f955100a 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -159,7 +159,7 @@ struct kexec_buf {
 };
 
 int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
-			       int (*func)(u64, u64, void *));
+			       int (*func)(struct resource *, void *));
 extern int kexec_add_buffer(struct kexec_buf *kbuf);
 int kexec_locate_mem_hole(struct kexec_buf *kbuf);
 #endif /* CONFIG_KEXEC_FILE */
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 9f48f4412297..e5bcd94c1efb 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -406,9 +406,10 @@ static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end,
 	return 1;
 }
 
-static int locate_mem_hole_callback(u64 start, u64 end, void *arg)
+static int locate_mem_hole_callback(struct resource *res, void *arg)
 {
 	struct kexec_buf *kbuf = (struct kexec_buf *)arg;
+	u64 start = res->start, end = res->end;
 	unsigned long sz = end - start + 1;
 
 	/* Returning 0 will take to next memory range */
@@ -437,7 +438,7 @@ static int locate_mem_hole_callback(u64 start, u64 end, void *arg)
  * func returning non-zero, then zero will be returned.
  */
 int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
-			       int (*func)(u64, u64, void *))
+			       int (*func)(struct resource *, void *))
 {
 	if (kbuf->image->type == KEXEC_TYPE_CRASH)
 		return walk_iomem_res_desc(crashk_res.desc,
diff --git a/kernel/resource.c b/kernel/resource.c
index 7323c1b636cd..8430042fa77b 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -402,14 +402,15 @@ static int find_next_iomem_res(struct resource *res, unsigned long desc,
 
 static int __walk_iomem_res_desc(struct resource *res, unsigned long desc,
 				 bool first_level_children_only,
-				 void *arg, int (*func)(u64, u64, void *))
+				 void *arg,
+				 int (*func)(struct resource *, void *))
 {
 	u64 orig_end = res->end;
 	int ret = -1;
 
 	while ((res->start < res->end) &&
 	       !find_next_iomem_res(res, desc, first_level_children_only)) {
-		ret = (*func)(res->start, res->end, arg);
+		ret = (*func)(res, arg);
 		if (ret)
 			break;
 
@@ -435,7 +436,7 @@ static int __walk_iomem_res_desc(struct resource *res, unsigned long desc,
  * <linux/ioport.h> and set it in 'desc' of a target resource entry.
  */
 int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
-		u64 end, void *arg, int (*func)(u64, u64, void *))
+		u64 end, void *arg, int (*func)(struct resource *, void *))
 {
 	struct resource res;
 
@@ -454,7 +455,7 @@ int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
  * ranges.
  */
 int walk_system_ram_res(u64 start, u64 end, void *arg,
-				int (*func)(u64, u64, void *))
+				int (*func)(struct resource *, void *))
 {
 	struct resource res;
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (8 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 09/17] resource: Provide resource struct in resource walk callback Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-28 16:23   ` Borislav Petkov
  2017-09-27 15:13 ` [Part1 PATCH v5 11/17] x86/mm: Add DMA support for SEV memory encryption Brijesh Singh
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Kirill A. Shutemov, Laura Abbott,
	Andy Lutomirski, Jérôme Glisse, Andrew Morton,
	Dan Williams, Kees Cook, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

In order for memory pages to be properly mapped when SEV is active, we
need to use the PAGE_KERNEL protection attribute as the base protection.
This will insure that memory mapping of, e.g. ACPI tables, receives the
proper mapping attributes.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/mm/ioremap.c  | 79 ++++++++++++++++++++++++++++++++++++++++++--------
 include/linux/ioport.h |  3 ++
 kernel/resource.c      | 19 ++++++++++++
 3 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 52cc0f4ed494..6e4573b1da34 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -27,6 +27,11 @@
 
 #include "physaddr.h"
 
+struct ioremap_mem_flags {
+	bool system_ram;
+	bool desc_other;
+};
+
 /*
  * Fix up the linear direct mapping of the kernel to avoid cache attribute
  * conflicts.
@@ -56,17 +61,59 @@ int ioremap_change_attr(unsigned long vaddr, unsigned long size,
 	return err;
 }
 
-static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages,
-			       void *arg)
+static bool __ioremap_check_ram(struct resource *res)
 {
+	unsigned long start_pfn, stop_pfn;
 	unsigned long i;
 
-	for (i = 0; i < nr_pages; ++i)
-		if (pfn_valid(start_pfn + i) &&
-		    !PageReserved(pfn_to_page(start_pfn + i)))
-			return 1;
+	if ((res->flags & IORESOURCE_SYSTEM_RAM) != IORESOURCE_SYSTEM_RAM)
+		return false;
 
-	return 0;
+	start_pfn = (res->start + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	stop_pfn = (res->end + 1) >> PAGE_SHIFT;
+	if (stop_pfn > start_pfn) {
+		for (i = 0; i < (stop_pfn - start_pfn); ++i)
+			if (pfn_valid(start_pfn + i) &&
+			    !PageReserved(pfn_to_page(start_pfn + i)))
+				return true;
+	}
+
+	return false;
+}
+
+static int __ioremap_check_desc_other(struct resource *res)
+{
+	return (res->desc != IORES_DESC_NONE);
+}
+
+static int __ioremap_res_check(struct resource *res, void *arg)
+{
+	struct ioremap_mem_flags *flags = arg;
+
+	if (!flags->system_ram)
+		flags->system_ram = __ioremap_check_ram(res);
+
+	if (!flags->desc_other)
+		flags->desc_other = __ioremap_check_desc_other(res);
+
+	return flags->system_ram && flags->desc_other;
+}
+
+/*
+ * To avoid multiple resource walks, this function walks resources marked as
+ * IORESOURCE_MEM and IORESOURCE_BUSY and looking for system RAM and/or a
+ * resource described not as IORES_DESC_NONE (e.g. IORES_DESC_ACPI_TABLES).
+ */
+static void __ioremap_check_mem(resource_size_t addr, unsigned long size,
+				struct ioremap_mem_flags *flags)
+{
+	u64 start, end;
+
+	start = (u64)addr;
+	end = start + size - 1;
+	memset(flags, 0, sizeof(*flags));
+
+	walk_mem_res(start, end, flags, __ioremap_res_check);
 }
 
 /*
@@ -87,9 +134,10 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
 		unsigned long size, enum page_cache_mode pcm, void *caller)
 {
 	unsigned long offset, vaddr;
-	resource_size_t pfn, last_pfn, last_addr;
+	resource_size_t last_addr;
 	const resource_size_t unaligned_phys_addr = phys_addr;
 	const unsigned long unaligned_size = size;
+	struct ioremap_mem_flags mem_flags;
 	struct vm_struct *area;
 	enum page_cache_mode new_pcm;
 	pgprot_t prot;
@@ -108,13 +156,12 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
 		return NULL;
 	}
 
+	__ioremap_check_mem(phys_addr, size, &mem_flags);
+
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
 	 */
-	pfn      = phys_addr >> PAGE_SHIFT;
-	last_pfn = last_addr >> PAGE_SHIFT;
-	if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
-					  __ioremap_check_ram) == 1) {
+	if (mem_flags.system_ram) {
 		WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n",
 			  &phys_addr, &last_addr);
 		return NULL;
@@ -146,7 +193,15 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
 		pcm = new_pcm;
 	}
 
+	/*
+	 * If the page being mapped is in memory and SEV is active then
+	 * make sure the memory encryption attribute is enabled in the
+	 * resulting mapping.
+	 */
 	prot = PAGE_KERNEL_IO;
+	if (sev_active() && mem_flags.desc_other)
+		prot = pgprot_encrypted(prot);
+
 	switch (pcm) {
 	case _PAGE_CACHE_MODE_UC:
 	default:
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 617d8a2aac67..c04d584ab5a1 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -270,6 +270,9 @@ extern int
 walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
 		void *arg, int (*func)(unsigned long, unsigned long, void *));
 extern int
+walk_mem_res(u64 start, u64 end, void *arg,
+	     int (*func)(struct resource *, void *));
+extern int
 walk_system_ram_res(u64 start, u64 end, void *arg,
 		    int (*func)(struct resource *, void *));
 extern int
diff --git a/kernel/resource.c b/kernel/resource.c
index 8430042fa77b..54ba6de3757c 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -397,6 +397,8 @@ static int find_next_iomem_res(struct resource *res, unsigned long desc,
 		res->start = p->start;
 	if (res->end > p->end)
 		res->end = p->end;
+	res->flags = p->flags;
+	res->desc = p->desc;
 	return 0;
 }
 
@@ -467,6 +469,23 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
 				     arg, func);
 }
 
+/*
+ * This function calls the @func callback against all memory ranges, which
+ * are ranges marked as IORESOURCE_MEM and IORESOUCE_BUSY.
+ */
+int walk_mem_res(u64 start, u64 end, void *arg,
+		 int (*func)(struct resource *, void *))
+{
+	struct resource res;
+
+	res.start = start;
+	res.end = end;
+	res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+	return __walk_iomem_res_desc(&res, IORES_DESC_NONE, true,
+				     arg, func);
+}
+
 #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
 
 /*
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 11/17] x86/mm: Add DMA support for SEV memory encryption
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (9 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 12/17] x86/boot: Add early boot support when running with SEV active Brijesh Singh
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Konrad Rzeszutek Wilk, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

DMA access to encrypted memory cannot be performed when SEV is active.
In order for DMA to properly work when SEV is active, the SWIOTLB bounce
buffers must be used.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/mm/mem_encrypt.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/swiotlb.c             |  5 +--
 2 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 5ad6ea61bd1a..c301cecd7052 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -190,6 +190,70 @@ void __init sme_early_init(void)
 	/* 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 (sev_active())
+		swiotlb_force = SWIOTLB_FORCE;
+}
+
+static void *sev_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		       gfp_t gfp, unsigned long attrs)
+{
+	unsigned long dma_mask;
+	unsigned int order;
+	struct page *page;
+	void *vaddr = NULL;
+
+	dma_mask = dma_alloc_coherent_mask(dev, gfp);
+	order = get_order(size);
+
+	/*
+	 * Memory will be memset to zero after marking decrypted, so don't
+	 * bother clearing it before.
+	 */
+	gfp &= ~__GFP_ZERO;
+
+	page = alloc_pages_node(dev_to_node(dev), gfp, order);
+	if (page) {
+		dma_addr_t addr;
+
+		/*
+		 * Since we will be clearing the encryption bit, check the
+		 * mask with it already cleared.
+		 */
+		addr = __sme_clr(phys_to_dma(dev, page_to_phys(page)));
+		if ((addr + size) > dma_mask) {
+			__free_pages(page, get_order(size));
+		} else {
+			vaddr = page_address(page);
+			*dma_handle = addr;
+		}
+	}
+
+	if (!vaddr)
+		vaddr = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+
+	if (!vaddr)
+		return NULL;
+
+	/* Clear the SME encryption bit for DMA use if not swiotlb area */
+	if (!is_swiotlb_buffer(dma_to_phys(dev, *dma_handle))) {
+		set_memory_decrypted((unsigned long)vaddr, 1 << order);
+		memset(vaddr, 0, PAGE_SIZE << order);
+		*dma_handle = __sme_clr(*dma_handle);
+	}
+
+	return vaddr;
+}
+
+static void sev_free(struct device *dev, size_t size, void *vaddr,
+		     dma_addr_t dma_handle, unsigned long attrs)
+{
+	/* Set the SME encryption bit for re-use if not swiotlb area */
+	if (!is_swiotlb_buffer(dma_to_phys(dev, dma_handle)))
+		set_memory_encrypted((unsigned long)vaddr,
+				     1 << get_order(size));
+
+	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
 }
 
 /*
@@ -216,6 +280,20 @@ bool sev_active(void)
 }
 EXPORT_SYMBOL_GPL(sev_active);
 
+static const struct dma_map_ops sev_dma_ops = {
+	.alloc                  = sev_alloc,
+	.free                   = sev_free,
+	.map_page               = swiotlb_map_page,
+	.unmap_page             = swiotlb_unmap_page,
+	.map_sg                 = swiotlb_map_sg_attrs,
+	.unmap_sg               = swiotlb_unmap_sg_attrs,
+	.sync_single_for_cpu    = swiotlb_sync_single_for_cpu,
+	.sync_single_for_device = swiotlb_sync_single_for_device,
+	.sync_sg_for_cpu        = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device     = swiotlb_sync_sg_for_device,
+	.mapping_error          = swiotlb_dma_mapping_error,
+};
+
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void)
 {
@@ -225,6 +303,14 @@ void __init mem_encrypt_init(void)
 	/* Call into SWIOTLB to update the SWIOTLB DMA buffers */
 	swiotlb_update_mem_attributes();
 
+	/*
+	 * With SEV, DMA operations cannot use encryption. New DMA ops
+	 * are required in order to mark the DMA areas as decrypted or
+	 * to use bounce buffers.
+	 */
+	if (sev_active())
+		dma_ops = &sev_dma_ops;
+
 	pr_info("AMD Secure Memory Encryption (SME) active\n");
 }
 
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 8c6c83ef57a4..cea19aaf303c 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -507,8 +507,9 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
 	if (no_iotlb_memory)
 		panic("Can not allocate SWIOTLB buffer earlier and can't now provide you with the DMA bounce buffer");
 
-	if (sme_active())
-		pr_warn_once("SME is active and system is using DMA bounce buffers\n");
+	if (mem_encrypt_active())
+		pr_warn_once("%s is active and system is using DMA bounce buffers\n",
+			     sme_active() ? "SME" : "SEV");
 
 	mask = dma_get_seg_boundary(hwdev);
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 12/17] x86/boot: Add early boot support when running with SEV active
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (10 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 11/17] x86/mm: Add DMA support for SEV memory encryption Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-28 17:02   ` Borislav Petkov
  2017-09-27 15:13 ` [Part1 PATCH v5 13/17] x86/io: Unroll string I/O when SEV is active Brijesh Singh
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Konrad Rzeszutek Wilk, Kirill A. Shutemov,
	Laura Abbott, Andy Lutomirski, Kees Cook, Paolo Bonzini,
	Radim Krčmář,
	Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

Early in the boot process, add checks to determine if the kernel is
running with Secure Encrypted Virtualization (SEV) active.

Checking for SEV requires checking that the kernel is running under a
hypervisor (CPUID 0x00000001, bit 31), that the SEV feature is available
(CPUID 0x8000001f, bit 1) and then checking a non-interceptable SEV MSR
(0xc0010131, bit 0).

This check is required so that during early compressed kernel booting the
pagetables (both the boot pagetables and KASLR pagetables (if enabled) are
updated to include the encryption mask so that when the kernel is
decompressed into encrypted memory, it can boot properly.

After the kernel is decompressed and continues booting the same logic is
used to check if SEV is active and set a flag indicating so.  This allows
us to distinguish between SME and SEV, each of which have unique
differences in how certain things are handled: e.g. DMA (always bounce
buffered with SEV) or EFI tables (always access decrypted with SME).

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/boot/compressed/Makefile      |   1 +
 arch/x86/boot/compressed/head_64.S     |  16 +++++
 arch/x86/boot/compressed/mem_encrypt.S | 120 +++++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/misc.h        |   2 +
 arch/x86/boot/compressed/pagetable.c   |   8 ++-
 arch/x86/include/asm/msr-index.h       |   3 +
 arch/x86/include/uapi/asm/kvm_para.h   |   1 -
 arch/x86/mm/mem_encrypt.c              |  50 +++++++++++---
 8 files changed, 186 insertions(+), 15 deletions(-)
 create mode 100644 arch/x86/boot/compressed/mem_encrypt.S

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 8a958274b54c..7fc5b7168e4f 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -77,6 +77,7 @@ vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o
 vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o
 ifdef CONFIG_X86_64
 	vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/pagetable.o
+	vmlinux-objs-y += $(obj)/mem_encrypt.o
 endif
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index b4a5d284391c..3dfad60720d0 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -130,6 +130,19 @@ ENTRY(startup_32)
  /*
   * Build early 4G boot pagetable
   */
+	/*
+	 * If SEV is active then set the encryption mask in the page tables.
+	 * This will insure that when the kernel is copied and decompressed
+	 * it will be done so encrypted.
+	 */
+	call	get_sev_encryption_bit
+	xorl	%edx, %edx
+	testl	%eax, %eax
+	jz	1f
+	subl	$32, %eax	/* Encryption bit is always above bit 31 */
+	bts	%eax, %edx	/* Set encryption mask for page tables */
+1:
+
 	/* Initialize Page tables to 0 */
 	leal	pgtable(%ebx), %edi
 	xorl	%eax, %eax
@@ -140,12 +153,14 @@ ENTRY(startup_32)
 	leal	pgtable + 0(%ebx), %edi
 	leal	0x1007 (%edi), %eax
 	movl	%eax, 0(%edi)
+	addl	%edx, 4(%edi)
 
 	/* Build Level 3 */
 	leal	pgtable + 0x1000(%ebx), %edi
 	leal	0x1007(%edi), %eax
 	movl	$4, %ecx
 1:	movl	%eax, 0x00(%edi)
+	addl	%edx, 0x04(%edi)
 	addl	$0x00001000, %eax
 	addl	$8, %edi
 	decl	%ecx
@@ -156,6 +171,7 @@ ENTRY(startup_32)
 	movl	$0x00000183, %eax
 	movl	$2048, %ecx
 1:	movl	%eax, 0(%edi)
+	addl	%edx, 4(%edi)
 	addl	$0x00200000, %eax
 	addl	$8, %edi
 	decl	%ecx
diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S
new file mode 100644
index 000000000000..54f5f6625a73
--- /dev/null
+++ b/arch/x86/boot/compressed/mem_encrypt.S
@@ -0,0 +1,120 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/processor-flags.h>
+#include <asm/msr.h>
+#include <asm/asm-offsets.h>
+
+	.text
+	.code32
+ENTRY(get_sev_encryption_bit)
+	xor	%eax, %eax
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	push	%ebx
+	push	%ecx
+	push	%edx
+	push	%edi
+
+	/*
+	 * RIP-relative addressing is needed to access the encryption bit
+	 * variable. Since we are running in 32-bit mode we need this call/pop
+	 * sequence to get the proper relative addressing.
+	 */
+	call	1f
+1:	popl	%edi
+	subl	$1b, %edi
+
+	movl	enc_bit(%edi), %eax
+	cmpl	$0, %eax
+	jge	.Lsev_exit
+
+	/* Check if running under a hypervisor */
+	movl	$1, %eax
+	cpuid
+	bt	$31, %ecx		/* Check the hypervisor bit */
+	jnc	.Lno_sev
+
+	movl	$0x80000000, %eax	/* CPUID to check the highest leaf */
+	cpuid
+	cmpl	$0x8000001f, %eax	/* See if 0x8000001f is available */
+	jb	.Lno_sev
+
+	/*
+	 * Check for the SEV feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 1
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$1, %eax		/* Check if SEV is available */
+	jnc	.Lno_sev
+
+	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
+	rdmsr
+	bt	$MSR_AMD64_SEV_ENABLED_BIT, %eax	/* Check if SEV is active */
+	jnc	.Lno_sev
+
+	movl	%ebx, %eax
+	andl	$0x3f, %eax		/* Return the encryption bit location */
+	movl	%eax, enc_bit(%edi)
+	jmp	.Lsev_exit
+
+.Lno_sev:
+	xor	%eax, %eax
+	movl	%eax, enc_bit(%edi)
+
+.Lsev_exit:
+	pop	%edi
+	pop	%edx
+	pop	%ecx
+	pop	%ebx
+
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+	ret
+ENDPROC(get_sev_encryption_bit)
+
+	.code64
+ENTRY(get_sev_encryption_mask)
+	xor	%rax, %rax
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	push	%rbp
+	push	%rdx
+
+	movq	%rsp, %rbp		/* Save current stack pointer */
+
+	call	get_sev_encryption_bit	/* Get the encryption bit position */
+	testl	%eax, %eax
+	jz	.Lno_sev_mask
+
+	xor	%rdx, %rdx
+	bts	%rax, %rdx		/* Create the encryption mask */
+	mov	%rdx, %rax		/* ... and return it */
+
+.Lno_sev_mask:
+	movq	%rbp, %rsp		/* Restore original stack pointer */
+
+	pop	%rdx
+	pop	%rbp
+#endif
+
+	ret
+ENDPROC(get_sev_encryption_mask)
+
+	.data
+enc_bit:
+	.int	0xffffffff
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 766a5211f827..38c5f0e13f7d 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -108,4 +108,6 @@ static inline void console_init(void)
 { }
 #endif
 
+unsigned long get_sev_encryption_mask(void);
+
 #endif
diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c
index f1aa43854bed..a577329d84c5 100644
--- a/arch/x86/boot/compressed/pagetable.c
+++ b/arch/x86/boot/compressed/pagetable.c
@@ -76,16 +76,18 @@ static unsigned long top_level_pgt;
  * Mapping information structure passed to kernel_ident_mapping_init().
  * Due to relocation, pointers must be assigned at run time not build time.
  */
-static struct x86_mapping_info mapping_info = {
-	.page_flag       = __PAGE_KERNEL_LARGE_EXEC,
-};
+static struct x86_mapping_info mapping_info;
 
 /* Locates and clears a region for a new top level page table. */
 void initialize_identity_maps(void)
 {
+	unsigned long sev_me_mask = get_sev_encryption_mask();
+
 	/* Init mapping_info with run-time function/buffer pointers. */
 	mapping_info.alloc_pgt_page = alloc_pgt_page;
 	mapping_info.context = &pgt_data;
+	mapping_info.page_flag = __PAGE_KERNEL_LARGE_EXEC | sev_me_mask;
+	mapping_info.kernpg_flag = _KERNPG_TABLE | sev_me_mask;
 
 	/*
 	 * It should be impossible for this not to already be true,
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 17f5c12e1afd..4a4e7d72b565 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -323,6 +323,9 @@
 #define MSR_AMD64_IBSBRTARGET		0xc001103b
 #define MSR_AMD64_IBSOPDATA4		0xc001103d
 #define MSR_AMD64_IBS_REG_COUNT_MAX	8 /* includes MSR_AMD64_IBSBRTARGET */
+#define MSR_AMD64_SEV			0xc0010131
+#define MSR_AMD64_SEV_ENABLED_BIT	0
+#define MSR_AMD64_SEV_ENABLED		BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
 
 /* Fam 17h MSRs */
 #define MSR_F17H_IRPERF			0xc00000e9
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
index a965e5b0d328..c202ba3fba0f 100644
--- a/arch/x86/include/uapi/asm/kvm_para.h
+++ b/arch/x86/include/uapi/asm/kvm_para.h
@@ -109,5 +109,4 @@ struct kvm_vcpu_pv_apf_data {
 #define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
 #define KVM_PV_EOI_DISABLED 0x0
 
-
 #endif /* _UAPI_ASM_X86_KVM_PARA_H */
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index c301cecd7052..bc6ba4cbe9b4 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -311,7 +311,9 @@ void __init mem_encrypt_init(void)
 	if (sev_active())
 		dma_ops = &sev_dma_ops;
 
-	pr_info("AMD Secure Memory Encryption (SME) active\n");
+	pr_info("AMD %s active\n",
+		sev_active() ? "Secure Encrypted Virtualization (SEV)"
+			     : "Secure Memory Encryption (SME)");
 }
 
 void swiotlb_set_mem_attributes(void *vaddr, unsigned long size)
@@ -639,37 +641,63 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 {
 	const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
 	unsigned int eax, ebx, ecx, edx;
+	unsigned long feature_mask;
 	bool active_by_default;
 	unsigned long me_mask;
 	char buffer[16];
 	u64 msr;
 
-	/* Check for the SME support leaf */
+	/* Check for the SME/SEV support leaf */
 	eax = 0x80000000;
 	ecx = 0;
 	native_cpuid(&eax, &ebx, &ecx, &edx);
 	if (eax < 0x8000001f)
 		return;
 
+#define AMD_SME_BIT	BIT(0)
+#define AMD_SEV_BIT	BIT(1)
 	/*
-	 * Check for the SME feature:
-	 *   CPUID Fn8000_001F[EAX] - Bit 0
-	 *     Secure Memory Encryption support
-	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
-	 *     Pagetable bit position used to indicate encryption
+	 * Set the feature mask (SME or SEV) based on whether we are
+	 * running under a hypervisor.
+	 */
+	eax = 1;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	feature_mask = (ecx & BIT(31)) ? AMD_SEV_BIT : AMD_SME_BIT;
+
+	/*
+	 * Check for the SME/SEV feature:
+	 *   CPUID Fn8000_001F[EAX]
+	 *   - Bit 0 - Secure Memory Encryption support
+	 *   - Bit 1 - Secure Encrypted Virtualization support
+	 *   CPUID Fn8000_001F[EBX]
+	 *   - Bits 5:0 - Pagetable bit position used to indicate encryption
 	 */
 	eax = 0x8000001f;
 	ecx = 0;
 	native_cpuid(&eax, &ebx, &ecx, &edx);
-	if (!(eax & 1))
+	if (!(eax & feature_mask))
 		return;
 
 	me_mask = 1UL << (ebx & 0x3f);
 
-	/* Check if SME is enabled */
-	msr = __rdmsr(MSR_K8_SYSCFG);
-	if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
+	/* Check if memory encryption is enabled */
+	if (feature_mask == AMD_SME_BIT) {
+		/* For SME, check the SYSCFG MSR */
+		msr = __rdmsr(MSR_K8_SYSCFG);
+		if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
+			return;
+	} else {
+		/* For SEV, check the SEV MSR */
+		msr = __rdmsr(MSR_AMD64_SEV);
+		if (!(msr & MSR_AMD64_SEV_ENABLED))
+			return;
+
+		/* SEV state cannot be controlled by a command line option */
+		sme_me_mask = me_mask;
+		sev_enabled = true;
 		return;
+	}
 
 	/*
 	 * Fixups have not been applied to phys_base yet and we're running
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 13/17] x86/io: Unroll string I/O when SEV is active
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (11 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 12/17] x86/boot: Add early boot support when running with SEV active Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-28 17:51   ` Borislav Petkov
  2017-09-27 15:13 ` [Part1 PATCH v5 14/17] x86: Add support for changing memory encryption attribute in early boot Brijesh Singh
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Shevchenko, David Laight, Arnd Bergmann,
	Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

Secure Encrypted Virtualization (SEV) does not support string I/O, so
unroll the string I/O operation into a loop operating on one element at
a time.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: David Laight <David.Laight@ACULAB.COM>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/include/asm/io.h | 42 ++++++++++++++++++++++++++++++++++++++----
 arch/x86/mm/mem_encrypt.c |  8 ++++++++
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index c40a95c33bb8..a785270b53e1 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -265,6 +265,20 @@ static inline void slow_down_io(void)
 
 #endif
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+
+extern struct static_key_false __sev;
+static inline bool sev_key_active(void)
+{
+	return static_branch_unlikely(&__sev);
+}
+
+#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)		\
 {									\
@@ -295,14 +309,34 @@ static inline unsigned type in##bwl##_p(int port)			\
 									\
 static inline void outs##bwl(int port, const void *addr, unsigned long count) \
 {									\
-	asm volatile("rep; outs" #bwl					\
-		     : "+S"(addr), "+c"(count) : "d"(port) : "memory");	\
+	if (sev_key_active()) {						\
+		unsigned type *value = (unsigned type *)addr;		\
+		while (count) {						\
+			out##bwl(*value, port);				\
+			value++;					\
+			count--;					\
+		}							\
+	} else {							\
+		asm volatile("rep; outs" #bwl				\
+			     : "+S"(addr), "+c"(count)			\
+			     : "d"(port) : "memory");			\
+	}								\
 }									\
 									\
 static inline void ins##bwl(int port, void *addr, unsigned long count)	\
 {									\
-	asm volatile("rep; ins" #bwl					\
-		     : "+D"(addr), "+c"(count) : "d"(port) : "memory");	\
+	if (sev_key_active()) {						\
+		unsigned type *value = (unsigned type *)addr;		\
+		while (count) {						\
+			*value = in##bwl(port);				\
+			value++;					\
+			count--;					\
+		}							\
+	} else {							\
+		asm volatile("rep; ins" #bwl				\
+			     : "+D"(addr), "+c"(count)			\
+			     : "d"(port) : "memory");			\
+	}								\
 }
 
 BUILDIO(b, b, char)
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index bc6ba4cbe9b4..05c3cb9fb442 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -39,6 +39,8 @@ static char sme_cmdline_off[] __initdata = "off";
  */
 u64 sme_me_mask __section(.data) = 0;
 EXPORT_SYMBOL_GPL(sme_me_mask);
+DEFINE_STATIC_KEY_FALSE(__sev);
+EXPORT_SYMBOL_GPL(__sev);
 
 static bool sev_enabled;
 
@@ -311,6 +313,12 @@ void __init mem_encrypt_init(void)
 	if (sev_active())
 		dma_ops = &sev_dma_ops;
 
+	/*
+	 * With SEV, we need to unroll the rep string I/O instructions.
+	 */
+	if (sev_active())
+		static_branch_enable(&__sev);
+
 	pr_info("AMD %s active\n",
 		sev_active() ? "Secure Encrypted Virtualization (SEV)"
 			     : "Secure Memory Encryption (SME)");
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 14/17] x86: Add support for changing memory encryption attribute in early boot
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (12 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 13/17] x86/io: Unroll string I/O when SEV is active Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-27 15:13 ` [Part1 PATCH v5 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED Brijesh Singh
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Tom Lendacky

Some KVM-specific custom MSRs share the guest physical address with the
hypervisor in early boot. When SEV is active, the shared physical address
must be mapped with memory encryption attribute cleared so that both
hypervisor and guest can access the data.

Add APIs to change the memory encryption attribute in early boot code.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/include/asm/mem_encrypt.h |   8 +++
 arch/x86/mm/mem_encrypt.c          | 121 +++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 2b024741bce9..3ba68c92be1b 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -42,6 +42,9 @@ void __init sme_early_init(void);
 void __init sme_encrypt_kernel(void);
 void __init sme_enable(struct boot_params *bp);
 
+int __init early_set_memory_decrypted(resource_size_t paddr, unsigned long size);
+int __init early_set_memory_encrypted(resource_size_t paddr, unsigned long size);
+
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void);
 
@@ -70,6 +73,11 @@ static inline void __init sme_enable(struct boot_params *bp) { }
 static inline bool sme_active(void) { return false; }
 static inline bool sev_active(void) { return false; }
 
+static inline int __init
+early_set_memory_decrypted(resource_size_t paddr, unsigned long size) { return 0; }
+static inline int __init
+early_set_memory_encrypted(resource_size_t paddr, unsigned long size) { return 0; }
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 /*
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 05c3cb9fb442..2a1142150372 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -28,6 +28,8 @@
 #include <asm/msr.h>
 #include <asm/cmdline.h>
 
+#include "mm_internal.h"
+
 static char sme_cmdline_arg[] __initdata = "mem_encrypt";
 static char sme_cmdline_on[]  __initdata = "on";
 static char sme_cmdline_off[] __initdata = "off";
@@ -258,6 +260,125 @@ static void sev_free(struct device *dev, size_t size, void *vaddr,
 	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
 }
 
+static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
+{
+	pgprot_t old_prot, new_prot;
+	unsigned long pfn;
+	pte_t new_pte;
+
+	switch (level) {
+	case PG_LEVEL_4K:
+		pfn = pte_pfn(*kpte);
+		old_prot = pte_pgprot(*kpte);
+		break;
+	case PG_LEVEL_2M:
+		pfn = pmd_pfn(*(pmd_t *)kpte);
+		old_prot = pmd_pgprot(*(pmd_t *)kpte);
+		break;
+	case PG_LEVEL_1G:
+		pfn = pud_pfn(*(pud_t *)kpte);
+		old_prot = pud_pgprot(*(pud_t *)kpte);
+		break;
+	default:
+		return;
+	}
+
+	new_prot = old_prot;
+	if (enc)
+		pgprot_val(new_prot) |= _PAGE_ENC;
+	else
+		pgprot_val(new_prot) &= ~_PAGE_ENC;
+
+	/* if prot is same then do nothing */
+	if (pgprot_val(old_prot) == pgprot_val(new_prot))
+		return;
+
+	new_pte = pfn_pte(pfn, new_prot);
+	set_pte_atomic(kpte, new_pte);
+}
+
+static int __init early_set_memory_enc_dec(resource_size_t paddr,
+					   unsigned long size, bool enc)
+{
+	unsigned long vaddr, vaddr_end, vaddr_next;
+	unsigned long psize, pmask;
+	int split_page_size_mask;
+	pte_t *kpte;
+	int level, ret;
+
+	vaddr = (unsigned long)__va(paddr);
+	vaddr_next = vaddr;
+	vaddr_end = vaddr + size;
+
+	/*
+	 * We are going to change the physical page attribute from C=1 to C=0
+	 * or vice versa. Flush the caches to ensure that data is written into
+	 * memory with correct C-bit before we change attribute.
+	 */
+	clflush_cache_range(__va(paddr), size);
+
+	for (; vaddr < vaddr_end; vaddr = vaddr_next) {
+		kpte = lookup_address(vaddr, &level);
+		if (!kpte || pte_none(*kpte)) {
+			ret = 1;
+			goto out;
+		}
+
+		if (level == PG_LEVEL_4K) {
+			__set_clr_pte_enc(kpte, level, enc);
+			vaddr_next = (vaddr & PAGE_MASK) + PAGE_SIZE;
+			continue;
+		}
+
+		psize = page_level_size(level);
+		pmask = page_level_mask(level);
+
+		/*
+		 * Check, whether we can change the large page in one go.
+		 * We request a split, when the address is not aligned and
+		 * the number of pages to set/clear encryption bit is smaller
+		 * than the number of pages in the large page.
+		 */
+		if (vaddr == (vaddr & pmask) &&
+			((vaddr_end - vaddr) >= psize)) {
+			__set_clr_pte_enc(kpte, level, enc);
+			vaddr_next = (vaddr & pmask) + psize;
+			continue;
+		}
+
+		/*
+		 * virtual address is part of large page, create the page table
+		 * mapping to use smaller pages (4K or 2M). If virtual address
+		 * is part of 2M page the we request spliting the large page
+		 * into 4K, similarly 1GB large page is requested to split into
+		 * 2M pages.
+		 */
+		if (level == PG_LEVEL_2M)
+			split_page_size_mask = 0;
+		else
+			split_page_size_mask = 1 << PG_LEVEL_2M;
+
+		kernel_physical_mapping_init(__pa(vaddr & pmask),
+					     __pa((vaddr_end & pmask) + psize),
+					     split_page_size_mask);
+	}
+
+	ret = 0;
+out:
+	__flush_tlb_all();
+	return ret;
+}
+
+int __init early_set_memory_decrypted(resource_size_t paddr, unsigned long size)
+{
+	return early_set_memory_enc_dec(paddr, size, false);
+}
+
+int __init early_set_memory_encrypted(resource_size_t paddr, unsigned long size)
+{
+	return early_set_memory_enc_dec(paddr, size, true);
+}
+
 /*
  * SME and SEV are very similar but they are not the same, so there are
  * times that the kernel will need to distinguish between SME and SEV. The
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (13 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 14/17] x86: Add support for changing memory encryption attribute in early boot Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-28 20:32   ` Borislav Petkov
  2017-09-27 15:13 ` [Part1 PATCH v5 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active Brijesh Singh
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Arnd Bergmann, Tejun Heo, Christoph Lameter,
	linux-arch, Tom Lendacky

KVM guest defines three per-CPU variables (steal-time, apf_reason, and
avic_eio) which are shared between a guest and a hypervisor. When SEV
is active, memory is encrypted with a guest-specific key, and if the
guest OS wants to share the memory region with the hypervisor then it
must clear the C-bit (i.e set decrypted) before sharing it.

DEFINE_PER_CPU_DECRYPTED can be used to define the per-CPU variables
which will be shared between a guest and a hypervisor.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Tejun Heo <tj@kernel.org>
Cc: Christoph Lameter <cl@linux.com>
Cc: linux-arch@vger.kernel.org
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Acked-by: Tejun Heo <tj@kernel.org>
---
 include/asm-generic/vmlinux.lds.h | 19 +++++++++++++++++++
 include/linux/percpu-defs.h       | 15 +++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8acfc1e099e1..2dd54c3e1a8a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -778,6 +778,24 @@
 #endif
 
 /*
+ * Memory encryption operates on a page basis. Since we need to clear
+ * the memory encryption mask for this section, it needs to be aligned
+ * on a page boundary and be a page-size multiple in length.
+ *
+ * Note: We use a separate section so that only this section gets
+ * decrypted to avoid exposing more than we wish.
+ */
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+#define PERCPU_DECRYPTED_SECTION					\
+	. = ALIGN(PAGE_SIZE);						\
+	*(.data..percpu..decrypted)					\
+	. = ALIGN(PAGE_SIZE);
+#else
+#define PERCPU_DECRYPTED_SECTION
+#endif
+
+
+/*
  * Default discarded sections.
  *
  * Some archs want to discard exit text/data at runtime rather than
@@ -815,6 +833,7 @@
 	. = ALIGN(cacheline);						\
 	*(.data..percpu)						\
 	*(.data..percpu..shared_aligned)				\
+	PERCPU_DECRYPTED_SECTION					\
 	VMLINUX_SYMBOL(__per_cpu_end) = .;
 
 /**
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 8f16299ca068..2d2096ba1cfe 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -173,6 +173,21 @@
 	DEFINE_PER_CPU_SECTION(type, name, "..read_mostly")
 
 /*
+ * Declaration/definition used for per-CPU variables that should be accessed
+ * as decrypted when memory encryption is enabled in the guest.
+ */
+#if defined(CONFIG_VIRTUALIZATION) && defined(CONFIG_AMD_MEM_ENCRYPT)
+
+#define DECLARE_PER_CPU_DECRYPTED(type, name)				\
+	DECLARE_PER_CPU_SECTION(type, name, "..decrypted")
+
+#define DEFINE_PER_CPU_DECRYPTED(type, name)				\
+	DEFINE_PER_CPU_SECTION(type, name, "..decrypted")
+#else
+#define DEFINE_PER_CPU_DECRYPTED(type, name)	DEFINE_PER_CPU(type, name)
+#endif
+
+/*
  * Intermodule exports for per-CPU variables.  sparse forgets about
  * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
  * noop if __CHECKER__.
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (14 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-29  5:51   ` Borislav Petkov
  2017-09-27 15:13 ` [Part1 PATCH v5 17/17] X86/KVM: Clear encryption attribute " Brijesh Singh
  2017-09-29  6:26 ` [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Borislav Petkov
  17 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Paolo Bonzini, Radim Krčmář,
	Tom Lendacky

When SEV is active, guest memory is encrypted with a guest-specific key, a
guest memory region shared with the hypervisor must be mapped as decrypted
before we can share it.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/kernel/kvm.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index aa60a08b65b1..2bd193ac78dc 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -75,8 +75,8 @@ static int parse_no_kvmclock_vsyscall(char *arg)
 
 early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
 
-static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
-static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
+static DEFINE_PER_CPU_DECRYPTED(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
+static DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64);
 static int has_steal_clock = 0;
 
 /*
@@ -305,7 +305,7 @@ static void kvm_register_steal_time(void)
 		cpu, (unsigned long long) slow_virt_to_phys(st));
 }
 
-static DEFINE_PER_CPU(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED;
+static DEFINE_PER_CPU_DECRYPTED(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED;
 
 static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
 {
@@ -419,9 +419,43 @@ void kvm_disable_steal_time(void)
 	wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
 }
 
+static inline void __init __set_percpu_decrypted(void *var, int size)
+{
+	unsigned long pa = slow_virt_to_phys(var);
+
+	/* decrypt the memory in-place */
+	sme_early_decrypt(pa, size);
+
+	/* clear the C-bit from the page table */
+	early_set_memory_decrypted(pa, size);
+}
+
+/*
+ * Iterate through all possible CPUs and map the memory region pointed
+ * by apf_reason, steal_time and kvm_apic_eoi as decrypted at once.
+ *
+ * Note: we iterate through all possible CPUs to ensure that CPUs
+ * hotplugged will have their per-cpu variable already mapped as
+ * decrypted.
+ */
+static void __init sev_map_percpu_data(void)
+{
+	int cpu;
+
+	if (!sev_active())
+		return;
+
+	for_each_possible_cpu(cpu) {
+		__set_percpu_decrypted(&per_cpu(apf_reason, cpu), sizeof(struct kvm_vcpu_pv_apf_data));
+		__set_percpu_decrypted(&per_cpu(steal_time, cpu), sizeof(struct kvm_steal_time));
+		__set_percpu_decrypted(&per_cpu(kvm_apic_eoi, cpu), sizeof(unsigned long));
+	}
+}
+
 #ifdef CONFIG_SMP
 static void __init kvm_smp_prepare_boot_cpu(void)
 {
+	sev_map_percpu_data();
 	kvm_guest_cpu_init();
 	native_smp_prepare_boot_cpu();
 	kvm_spinlock_init();
@@ -489,6 +523,7 @@ void __init kvm_guest_init(void)
 				      kvm_cpu_online, kvm_cpu_down_prepare) < 0)
 		pr_err("kvm_guest: Failed to install cpu hotplug callbacks\n");
 #else
+	sev_map_percpu_data();
 	kvm_guest_cpu_init();
 #endif
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 17/17] X86/KVM: Clear encryption attribute when SEV is active
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (15 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active Brijesh Singh
@ 2017-09-27 15:13 ` Brijesh Singh
  2017-09-29  6:26 ` [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Borislav Petkov
  17 siblings, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:13 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Paolo Bonzini, Radim Krčmář,
	Tom Lendacky

The guest physical memory area holding the struct pvclock_wall_clock and
struct pvclock_vcpu_time_info are shared with the hypervisor. It
periodically updates the contents of the memory. When SEV is active, we
must clear the encryption attributes from the shared memory pages so that
both hypervisor and guest can access the data.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/entry/vdso/vma.c  |  5 ++--
 arch/x86/kernel/kvmclock.c | 65 ++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 1911310959f8..d63053142b16 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -114,10 +114,11 @@ static int vvar_fault(const struct vm_special_mapping *sm,
 		struct pvclock_vsyscall_time_info *pvti =
 			pvclock_pvti_cpu0_va();
 		if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) {
-			ret = vm_insert_pfn(
+			ret = vm_insert_pfn_prot(
 				vma,
 				vmf->address,
-				__pa(pvti) >> PAGE_SHIFT);
+				__pa(pvti) >> PAGE_SHIFT,
+				pgprot_decrypted(vma->vm_page_prot));
 		}
 	} else if (sym_offset == image->sym_hvclock_page) {
 		struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page();
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index d88967659098..3de184be0887 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/sched/clock.h>
 
+#include <asm/mem_encrypt.h>
 #include <asm/x86_init.h>
 #include <asm/reboot.h>
 #include <asm/kvmclock.h>
@@ -45,7 +46,7 @@ early_param("no-kvmclock", parse_no_kvmclock);
 
 /* The hypervisor will put information about time periodically here */
 static struct pvclock_vsyscall_time_info *hv_clock;
-static struct pvclock_wall_clock wall_clock;
+static struct pvclock_wall_clock *wall_clock;
 
 struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void)
 {
@@ -64,15 +65,15 @@ static void kvm_get_wallclock(struct timespec *now)
 	int low, high;
 	int cpu;
 
-	low = (int)__pa_symbol(&wall_clock);
-	high = ((u64)__pa_symbol(&wall_clock) >> 32);
+	low = (int)slow_virt_to_phys(wall_clock);
+	high = ((u64)slow_virt_to_phys(wall_clock) >> 32);
 
 	native_write_msr(msr_kvm_wall_clock, low, high);
 
 	cpu = get_cpu();
 
 	vcpu_time = &hv_clock[cpu].pvti;
-	pvclock_read_wallclock(&wall_clock, vcpu_time, now);
+	pvclock_read_wallclock(wall_clock, vcpu_time, now);
 
 	put_cpu();
 }
@@ -249,11 +250,39 @@ static void kvm_shutdown(void)
 	native_machine_shutdown();
 }
 
+static phys_addr_t __init kvm_memblock_alloc(phys_addr_t size,
+					     phys_addr_t align)
+{
+	phys_addr_t mem;
+
+	mem = memblock_alloc(size, align);
+	if (!mem)
+		return 0;
+
+	if (sev_active()) {
+		if (early_set_memory_decrypted(mem, size))
+			goto e_free;
+	}
+
+	return mem;
+e_free:
+	memblock_free(mem, size);
+	return 0;
+}
+
+static void __init kvm_memblock_free(phys_addr_t addr, phys_addr_t size)
+{
+	if (sev_active())
+		early_set_memory_encrypted(addr, size);
+
+	memblock_free(addr, size);
+}
+
 void __init kvmclock_init(void)
 {
 	struct pvclock_vcpu_time_info *vcpu_time;
-	unsigned long mem;
-	int size, cpu;
+	unsigned long mem, mem_wall_clock;
+	int size, cpu, wall_clock_size;
 	u8 flags;
 
 	size = PAGE_ALIGN(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
@@ -267,21 +296,35 @@ void __init kvmclock_init(void)
 	} else if (!(kvmclock && kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)))
 		return;
 
-	printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
-		msr_kvm_system_time, msr_kvm_wall_clock);
+	wall_clock_size = PAGE_ALIGN(sizeof(struct pvclock_wall_clock));
+	mem_wall_clock = kvm_memblock_alloc(wall_clock_size, PAGE_SIZE);
+	if (!mem_wall_clock)
+		return;
 
-	mem = memblock_alloc(size, PAGE_SIZE);
-	if (!mem)
+	wall_clock = __va(mem_wall_clock);
+	memset(wall_clock, 0, wall_clock_size);
+
+	mem = kvm_memblock_alloc(size, PAGE_SIZE);
+	if (!mem) {
+		kvm_memblock_free(mem_wall_clock, wall_clock_size);
+		wall_clock = NULL;
 		return;
+	}
+
 	hv_clock = __va(mem);
 	memset(hv_clock, 0, size);
 
 	if (kvm_register_clock("primary cpu clock")) {
 		hv_clock = NULL;
-		memblock_free(mem, size);
+		kvm_memblock_free(mem, size);
+		kvm_memblock_free(mem_wall_clock, wall_clock_size);
+		wall_clock = NULL;
 		return;
 	}
 
+	printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
+		msr_kvm_system_time, msr_kvm_wall_clock);
+
 	if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))
 		pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes
  2017-09-27 15:13 ` [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes Brijesh Singh
@ 2017-09-27 15:53   ` Brijesh Singh
  2017-09-27 17:26     ` Borislav Petkov
  2017-09-27 19:17   ` [Part1 PATCH v5.1 " Brijesh Singh
  1 sibling, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 15:53 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: brijesh.singh, Tom Lendacky, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Borislav Petkov, Andy Lutomirski, John Ogness,
	Matt Fleming, Laura Abbott, Dan Williams, Kirill A. Shutemov



On 09/27/2017 10:13 AM, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> The current code checks only for sme_active() when determining whether
> to perform the encryption attribute change.  Include sev_active() in this
> check so that memory attribute changes can occur under SME and SEV.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: John Ogness <john.ogness@linutronix.de>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Cc: Laura Abbott <labbott@redhat.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: linux-kernel@vger.kernel.org
> Cc: x86@kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---

I just realized that I missed picking Boris R-b tag in the commit [1].
If another version is needed then I will include it. thanks

[1] https://marc.info/?l=kvm&m=150565715508940&w=2

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes
  2017-09-27 15:53   ` Brijesh Singh
@ 2017-09-27 17:26     ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-27 17:26 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Lutomirski, John Ogness,
	Matt Fleming, Laura Abbott, Dan Williams, Kirill A. Shutemov

On Wed, Sep 27, 2017 at 10:53:17AM -0500, Brijesh Singh wrote:
> I just realized that I missed picking Boris R-b tag in the commit [1].
> If another version is needed then I will include it. thanks

You can send it as a reply to this message by changing the subject to

[Part1 PATCH v5.1 06/17] x86/mm: Include SEV for encryption memory attribute changes

for example, so that reviewiers know this version supercedes the v5 one.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5.1 06/17] x86/mm: Include SEV for encryption memory attribute changes
  2017-09-27 15:13 ` [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes Brijesh Singh
  2017-09-27 15:53   ` Brijesh Singh
@ 2017-09-27 19:17   ` Brijesh Singh
  1 sibling, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-27 19:17 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, John Ogness, Matt Fleming,
	Laura Abbott, Dan Williams, Kirill A. Shutemov, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

The current code checks only for sme_active() when determining whether
to perform the encryption attribute change.  Include sev_active() in this
check so that memory attribute changes can occur under SME and SEV.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/mm/pageattr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index dfb7d657cf43..3fe68483463c 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1781,8 +1781,8 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
 	unsigned long start;
 	int ret;
 
-	/* Nothing to do if the SME is not active */
-	if (!sme_active())
+	/* Nothing to do if memory encryption is not active */
+	if (!mem_encrypt_active())
 		return 0;
 
 	/* Should not be working on unaligned addresses */
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-27 15:13 ` [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support Brijesh Singh
@ 2017-09-28  9:02   ` Borislav Petkov
  2017-09-28 18:48     ` Brijesh Singh
                       ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28  9:02 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Lutomirski

On Wed, Sep 27, 2017 at 10:13:14AM -0500, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> Provide support for Secure Encrypted Virtualization (SEV). This initial
> support defines a flag that is used by the kernel to determine if it is
> running with SEV active.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: linux-kernel@vger.kernel.org
> Cc: x86@kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  arch/x86/include/asm/mem_encrypt.h |  6 ++++++
>  arch/x86/mm/mem_encrypt.c          | 26 ++++++++++++++++++++++++++
>  include/linux/mem_encrypt.h        |  7 +++++--
>  3 files changed, 37 insertions(+), 2 deletions(-)

Reviewed-by: Borislav Petkov <bp@suse.de>

> +bool sev_active(void)
> +{
> +	return sme_me_mask && sev_enabled;

What I'm still missing is the chicken bit. I.e., to be able to boot with
"mem_encrypt=smeonly" or so, which disables the SEV side but can still
allow SME. For when SEV has issues and people want to disable it.

You can do the patch ontop of those and send it as a reply to this
thread - no need to wait to resend the whole thing again.

Thanks.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV
  2017-09-27 15:13 ` [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV Brijesh Singh
@ 2017-09-28 11:13   ` Borislav Petkov
  2017-09-28 16:20   ` [Part1 PATCH v5.1 " Brijesh Singh
  1 sibling, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28 11:13 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Lutomirski, Laura Abbott,
	Kirill A. Shutemov, Matt Fleming

On Wed, Sep 27, 2017 at 10:13:17AM -0500, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> When Secure Encrypted Virtualization (SEV) is active, boot data (such as
> EFI related data, setup data) is encrypted and needs to be accessed as
> such when mapped. Update the architecture override in early_memremap to
> keep the encryption attribute when mapping this data.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Laura Abbott <labbott@redhat.com>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Cc: linux-kernel@vger.kernel.org
> Cc: x86@kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  arch/x86/mm/ioremap.c | 44 ++++++++++++++++++++++++++++++--------------
>  1 file changed, 30 insertions(+), 14 deletions(-)

I already send a Reviewed-by for this one. Please be more careful when
reworking feedback.

Thanks.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5.1 05/17] x86/mm: Use encrypted access of boot related data with SEV
  2017-09-27 15:13 ` [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV Brijesh Singh
  2017-09-28 11:13   ` Borislav Petkov
@ 2017-09-28 16:20   ` Brijesh Singh
  1 sibling, 0 replies; 55+ messages in thread
From: Brijesh Singh @ 2017-09-28 16:20 UTC (permalink / raw)
  To: kvm, linux-kernel, x86
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Borislav Petkov, Andy Lutomirski, Laura Abbott,
	Kirill A. Shutemov, Matt Fleming, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

When Secure Encrypted Virtualization (SEV) is active, boot data (such as
EFI related data, setup data) is encrypted and needs to be accessed as
such when mapped. Update the architecture override in early_memremap to
keep the encryption attribute when mapping this data.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Laura Abbott <labbott@redhat.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/mm/ioremap.c | 44 ++++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 34f0e1847dd6..52cc0f4ed494 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -422,6 +422,9 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
  * areas should be mapped decrypted. And since the encryption key can
  * change across reboots, persistent memory should also be mapped
  * decrypted.
+ *
+ * If SEV is active, that implies that BIOS/UEFI also ran encrypted so
+ * only persistent memory should be mapped decrypted.
  */
 static bool memremap_should_map_decrypted(resource_size_t phys_addr,
 					  unsigned long size)
@@ -458,6 +461,11 @@ static bool memremap_should_map_decrypted(resource_size_t phys_addr,
 	case E820_TYPE_ACPI:
 	case E820_TYPE_NVS:
 	case E820_TYPE_UNUSABLE:
+		/* For SEV, these areas are encrypted */
+		if (sev_active())
+			break;
+		/* Fallthrough */
+
 	case E820_TYPE_PRAM:
 		return true;
 	default:
@@ -581,7 +589,7 @@ static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
 bool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size,
 				 unsigned long flags)
 {
-	if (!sme_active())
+	if (!mem_encrypt_active())
 		return true;
 
 	if (flags & MEMREMAP_ENC)
@@ -590,12 +598,13 @@ bool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size,
 	if (flags & MEMREMAP_DEC)
 		return false;
 
-	if (memremap_is_setup_data(phys_addr, size) ||
-	    memremap_is_efi_data(phys_addr, size) ||
-	    memremap_should_map_decrypted(phys_addr, size))
-		return false;
+	if (sme_active()) {
+		if (memremap_is_setup_data(phys_addr, size) ||
+		    memremap_is_efi_data(phys_addr, size))
+			return false;
+	}
 
-	return true;
+	return !memremap_should_map_decrypted(phys_addr, size);
 }
 
 /*
@@ -608,17 +617,24 @@ pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
 					     unsigned long size,
 					     pgprot_t prot)
 {
-	if (!sme_active())
+	bool encrypted_prot;
+
+	if (!mem_encrypt_active())
 		return prot;
 
-	if (early_memremap_is_setup_data(phys_addr, size) ||
-	    memremap_is_efi_data(phys_addr, size) ||
-	    memremap_should_map_decrypted(phys_addr, size))
-		prot = pgprot_decrypted(prot);
-	else
-		prot = pgprot_encrypted(prot);
+	encrypted_prot = true;
+
+	if (sme_active()) {
+		if (early_memremap_is_setup_data(phys_addr, size) ||
+		    memremap_is_efi_data(phys_addr, size))
+			encrypted_prot = false;
+	}
+
+	if (encrypted_prot && memremap_should_map_decrypted(phys_addr, size))
+		encrypted_prot = false;
 
-	return prot;
+	return encrypted_prot ? pgprot_encrypted(prot)
+			      : pgprot_decrypted(prot);
 }
 
 bool phys_mem_access_encrypted(unsigned long phys_addr, unsigned long size)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages
  2017-09-27 15:13 ` [Part1 PATCH v5 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages Brijesh Singh
@ 2017-09-28 16:23   ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28 16:23 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Kirill A. Shutemov, Laura Abbott,
	Andy Lutomirski, Jérôme Glisse, Andrew Morton,
	Dan Williams, Kees Cook

On Wed, Sep 27, 2017 at 10:13:22AM -0500, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> In order for memory pages to be properly mapped when SEV is active, we
> need to use the PAGE_KERNEL protection attribute as the base protection.
> This will insure that memory mapping of, e.g. ACPI tables, receives the
> proper mapping attributes.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Laura Abbott <labbott@redhat.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: "Jérôme Glisse" <jglisse@redhat.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  arch/x86/mm/ioremap.c  | 79 ++++++++++++++++++++++++++++++++++++++++++--------
>  include/linux/ioport.h |  3 ++
>  kernel/resource.c      | 19 ++++++++++++
>  3 files changed, 89 insertions(+), 12 deletions(-)

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 12/17] x86/boot: Add early boot support when running with SEV active
  2017-09-27 15:13 ` [Part1 PATCH v5 12/17] x86/boot: Add early boot support when running with SEV active Brijesh Singh
@ 2017-09-28 17:02   ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28 17:02 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Konrad Rzeszutek Wilk,
	Kirill A. Shutemov, Laura Abbott, Andy Lutomirski, Kees Cook,
	Paolo Bonzini, Radim Krčmář

On Wed, Sep 27, 2017 at 10:13:24AM -0500, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> Early in the boot process, add checks to determine if the kernel is
> running with Secure Encrypted Virtualization (SEV) active.
> 
> Checking for SEV requires checking that the kernel is running under a
> hypervisor (CPUID 0x00000001, bit 31), that the SEV feature is available
> (CPUID 0x8000001f, bit 1) and then checking a non-interceptable SEV MSR
> (0xc0010131, bit 0).
> 
> This check is required so that during early compressed kernel booting the
> pagetables (both the boot pagetables and KASLR pagetables (if enabled) are
> updated to include the encryption mask so that when the kernel is
> decompressed into encrypted memory, it can boot properly.
> 
> After the kernel is decompressed and continues booting the same logic is
> used to check if SEV is active and set a flag indicating so.  This allows
> us to distinguish between SME and SEV, each of which have unique
> differences in how certain things are handled: e.g. DMA (always bounce
> buffered with SEV) or EFI tables (always access decrypted with SME).
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Laura Abbott <labbott@redhat.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: "Radim Krčmář" <rkrcmar@redhat.com>
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  arch/x86/boot/compressed/Makefile      |   1 +
>  arch/x86/boot/compressed/head_64.S     |  16 +++++
>  arch/x86/boot/compressed/mem_encrypt.S | 120 +++++++++++++++++++++++++++++++++
>  arch/x86/boot/compressed/misc.h        |   2 +
>  arch/x86/boot/compressed/pagetable.c   |   8 ++-
>  arch/x86/include/asm/msr-index.h       |   3 +
>  arch/x86/include/uapi/asm/kvm_para.h   |   1 -
>  arch/x86/mm/mem_encrypt.c              |  50 +++++++++++---
>  8 files changed, 186 insertions(+), 15 deletions(-)
>  create mode 100644 arch/x86/boot/compressed/mem_encrypt.S

Reviewed-by: Borislav Petkov <bp@suse.de>

> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index c301cecd7052..bc6ba4cbe9b4 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -311,7 +311,9 @@ void __init mem_encrypt_init(void)
>  	if (sev_active())
>  		dma_ops = &sev_dma_ops;
>  
> -	pr_info("AMD Secure Memory Encryption (SME) active\n");
> +	pr_info("AMD %s active\n",
> +		sev_active() ? "Secure Encrypted Virtualization (SEV)"
> +			     : "Secure Memory Encryption (SME)");
>  }
>  
>  void swiotlb_set_mem_attributes(void *vaddr, unsigned long size)
> @@ -639,37 +641,63 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)

This function should be renamed to mem_encrypt_enable() or so now that
it enables SEV too. But this is for the TODO list and another, later
patchset.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 13/17] x86/io: Unroll string I/O when SEV is active
  2017-09-27 15:13 ` [Part1 PATCH v5 13/17] x86/io: Unroll string I/O when SEV is active Brijesh Singh
@ 2017-09-28 17:51   ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28 17:51 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Shevchenko, David Laight,
	Arnd Bergmann

On Wed, Sep 27, 2017 at 10:13:25AM -0500, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> Secure Encrypted Virtualization (SEV) does not support string I/O, so
> unroll the string I/O operation into a loop operating on one element at
> a time.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Cc: David Laight <David.Laight@ACULAB.COM>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  arch/x86/include/asm/io.h | 42 ++++++++++++++++++++++++++++++++++++++----
>  arch/x86/mm/mem_encrypt.c |  8 ++++++++
>  2 files changed, 46 insertions(+), 4 deletions(-)

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-28  9:02   ` Borislav Petkov
@ 2017-09-28 18:48     ` Brijesh Singh
  2017-09-28 19:23       ` Borislav Petkov
  2017-09-29 21:27     ` [Part1 PATCH v5.1 " Brijesh Singh
  2017-09-29 23:06     ` [Part1 PATCH v5 18/18] x86/mm: add 'sme' argument in mem_encrypt= Brijesh Singh
  2 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-28 18:48 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: brijesh.singh, kvm, linux-kernel, x86, Tom Lendacky,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski

Hi Boris,

On 09/28/2017 04:02 AM, Borislav Petkov wrote:
...

>> +bool sev_active(void)
>> +{
>> +	return sme_me_mask && sev_enabled;
> 
> What I'm still missing is the chicken bit. I.e., to be able to boot with
> "mem_encrypt=smeonly" or so, which disables the SEV side but can still
> allow SME. For when SEV has issues and people want to disable it.
> 


Let me understand the ask, are you saying that we need a method to disable the SEV
feature from the host OS so that Hypervisor will not be able to create a SEV guest?
Because once a guest is booted with SEV feature, there is no way to disable the SEV
feature from the guest.

i.e if "mem_encrypt=smeonly" is set then we clear X86_FEATURE_SEV capability flag
defined in [1].

[1] https://marc.info/?l=linux-kernel&m=150585470323923&w=2


> You can do the patch ontop of those and send it as a reply to this
> thread - no need to wait to resend the whole thing again.
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-28 18:48     ` Brijesh Singh
@ 2017-09-28 19:23       ` Borislav Petkov
  2017-09-29 12:28         ` Brijesh Singh
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28 19:23 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Lutomirski

Hi,

On Thu, Sep 28, 2017 at 01:48:48PM -0500, Brijesh Singh wrote:
> Let me understand the ask, are you saying that we need a method to disable the SEV
> feature from the host OS so that Hypervisor will not be able to create a SEV guest?
> Because once a guest is booted with SEV feature, there is no way to disable the SEV
> feature from the guest.
> 
> i.e if "mem_encrypt=smeonly" is set then we clear X86_FEATURE_SEV capability flag
> defined in [1].

So actually we need chicken bits to be able to *enable* both when
CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT is not set.

I.e.,

* mem_encrypt=on - both SME and SEV enabled

* mem_encrypt=smeonly - only SME, no SEV on the host. This option will
basically prevent from using any SEV guests and make the SEV part of the
code inactive. I.e., sev_active() and sev_enabled should be false. As
you say above, we should clear X86_FEATURE_SEV, yes.

* mem_encrypt=off - neither SME/SEV are enabled.

And =on and =off we already have.

How does that sound?

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED
  2017-09-27 15:13 ` [Part1 PATCH v5 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED Brijesh Singh
@ 2017-09-28 20:32   ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-28 20:32 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Arnd Bergmann, Tejun Heo, Christoph Lameter,
	linux-arch, Tom Lendacky

On Wed, Sep 27, 2017 at 10:13:27AM -0500, Brijesh Singh wrote:
> KVM guest defines three per-CPU variables (steal-time, apf_reason, and
> avic_eio) which are shared between a guest and a hypervisor. When SEV
> is active, memory is encrypted with a guest-specific key, and if the
> guest OS wants to share the memory region with the hypervisor then it
> must clear the C-bit (i.e set decrypted) before sharing it.
> 
> DEFINE_PER_CPU_DECRYPTED can be used to define the per-CPU variables
> which will be shared between a guest and a hypervisor.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Tejun Heo <tj@kernel.org>
> Cc: Christoph Lameter <cl@linux.com>
> Cc: linux-arch@vger.kernel.org
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> Acked-by: Tejun Heo <tj@kernel.org>
> ---
>  include/asm-generic/vmlinux.lds.h | 19 +++++++++++++++++++
>  include/linux/percpu-defs.h       | 15 +++++++++++++++
>  2 files changed, 34 insertions(+)

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active
  2017-09-27 15:13 ` [Part1 PATCH v5 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active Brijesh Singh
@ 2017-09-29  5:51   ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-29  5:51 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Paolo Bonzini, Radim Krčmář,
	Tom Lendacky

On Wed, Sep 27, 2017 at 10:13:28AM -0500, Brijesh Singh wrote:
> When SEV is active, guest memory is encrypted with a guest-specific key, a
> guest memory region shared with the hypervisor must be mapped as decrypted
> before we can share it.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: "Radim Krčmář" <rkrcmar@redhat.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: kvm@vger.kernel.org
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  arch/x86/kernel/kvm.c | 41 ++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 38 insertions(+), 3 deletions(-)

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (16 preceding siblings ...)
  2017-09-27 15:13 ` [Part1 PATCH v5 17/17] X86/KVM: Clear encryption attribute " Brijesh Singh
@ 2017-09-29  6:26 ` Borislav Petkov
  17 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-29  6:26 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Andy Lutomirski, Tom Lendacky, Paolo Bonzini,
	Radim Krčmář

On Wed, Sep 27, 2017 at 10:13:12AM -0500, Brijesh Singh wrote:
> This part of Secure Encrypted Virtualization (SEV) series focuses on the
> changes required in a guest OS for SEV support.

...

> This series is based on tip/master commit : a35205980288 (Merge branch 'WIP.x86/fpu').
> 
> Complete git tree is available: https://github.com/codomania/tip/tree/sev-v5-p1

Ok, so far so good, that part boots:

[    0.000000] AMD Secure Memory Encryption (SME) active

:-)

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-28 19:23       ` Borislav Petkov
@ 2017-09-29 12:28         ` Brijesh Singh
  2017-09-29 14:41           ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-29 12:28 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: brijesh.singh, kvm, linux-kernel, x86, Tom Lendacky,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski



On 9/28/17 2:23 PM, Borislav Petkov wrote:
...
> So actually we need chicken bits to be able to *enable* both when
> CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT is not set.
>
> I.e.,
>
> * mem_encrypt=on - both SME and SEV enabled
>
> * mem_encrypt=smeonly - only SME, no SEV on the host. This option will
> basically prevent from using any SEV guests and make the SEV part of the
> code inactive. I.e., sev_active() and sev_enabled should be false. As
> you say above, we should clear X86_FEATURE_SEV, yes.
>
> * mem_encrypt=off - neither SME/SEV are enabled.
>
> And =on and =off we already have.
>
> How does that sound?

if we are adding a chicken bits then I think we should do it for both
"smeonly" and "sevonly". We can boot host OS with SME disabled and SEV
enabled, and still be able to create the SEV guest from the hypervisor.

How about this ?

mem_encrypt=on     both SME and SEV enabled
mem_encrypt=sev    only SEV enabled
mem_encrypt=sme   only SME enabled
mem_encrypt=off     neither SME/SEV are enabled

-Brijesh

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-29 12:28         ` Brijesh Singh
@ 2017-09-29 14:41           ` Borislav Petkov
  2017-09-29 15:54             ` Brijesh Singh
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-09-29 14:41 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Lutomirski

On Fri, Sep 29, 2017 at 07:28:47AM -0500, Brijesh Singh wrote:
> if we are adding a chicken bits then I think we should do it for both
> "smeonly" and "sevonly". We can boot host OS with SME disabled and SEV
> enabled, and still be able to create the SEV guest from the hypervisor.

Sure, but is that a real use case? I mean, who would want to run
encrypted guests on an unencrypted hypervisor?

> How about this ?
> 
> mem_encrypt=on     both SME and SEV enabled
> mem_encrypt=sev    only SEV enabled
> mem_encrypt=sme   only SME enabled
> mem_encrypt=off     neither SME/SEV are enabled

I like those short mnemonics, ACK. Less typing is always good.

Thx.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-29 14:41           ` Borislav Petkov
@ 2017-09-29 15:54             ` Brijesh Singh
  2017-09-29 15:56               ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-29 15:54 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: brijesh.singh, kvm, linux-kernel, x86, Tom Lendacky,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski



On 09/29/2017 09:41 AM, Borislav Petkov wrote:
> On Fri, Sep 29, 2017 at 07:28:47AM -0500, Brijesh Singh wrote:
>> if we are adding a chicken bits then I think we should do it for both
>> "smeonly" and "sevonly". We can boot host OS with SME disabled and SEV
>> enabled, and still be able to create the SEV guest from the hypervisor.
> 
> Sure, but is that a real use case? I mean, who would want to run
> encrypted guests on an unencrypted hypervisor?
> 

In production, you do not want to run encrypted guest on an unencrypted
hypervisor -- I was thinking about the debug environment. We can start
with mem_encrypt=sme and if we see the need for 'sev' arg then we can
extend it later.

I am working on the patch and will send for the review. thanks

-Brijesh

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-29 15:54             ` Brijesh Singh
@ 2017-09-29 15:56               ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-29 15:56 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: kvm, linux-kernel, x86, Tom Lendacky, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Andy Lutomirski

On Fri, Sep 29, 2017 at 10:54:39AM -0500, Brijesh Singh wrote:
> In production, you do not want to run encrypted guest on an unencrypted
> hypervisor -- I was thinking about the debug environment. We can start
> with mem_encrypt=sme and if we see the need for 'sev' arg then we can
> extend it later.

Yap, exactly.

> I am working on the patch and will send for the review. thanks

Thanks.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5.1 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-28  9:02   ` Borislav Petkov
  2017-09-28 18:48     ` Brijesh Singh
@ 2017-09-29 21:27     ` Brijesh Singh
  2017-09-30  8:49       ` Borislav Petkov
  2017-09-29 23:06     ` [Part1 PATCH v5 18/18] x86/mm: add 'sme' argument in mem_encrypt= Brijesh Singh
  2 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-29 21:27 UTC (permalink / raw)
  To: bp
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Andy Lutomirski, linux-kernel, x86, Brijesh Singh

From: Tom Lendacky <thomas.lendacky@amd.com>

Provide support for Secure Encrypted Virtualization (SEV). This initial
support defines a flag that is used by the kernel to determine if it is
running with SEV active.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---

Hi Boris,

Similar to the sme_me_mask, sev_enabled must live in .data section otherwise it
will get zero'ed in clear_bss() and we will loose the value. I have encountered
this issue when booting SEV guest using qemu's -kernel option.

I have removed your R-b since was not sure if you are still okay with the change.

Changes:
 * move sev_enabled in .data section

 arch/x86/include/asm/mem_encrypt.h |  6 ++++++
 arch/x86/mm/mem_encrypt.c          | 26 ++++++++++++++++++++++++++
 include/linux/mem_encrypt.h        |  7 +++++--
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 6a77c63540f7..2b024741bce9 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -47,6 +47,9 @@ void __init mem_encrypt_init(void);
 
 void swiotlb_set_mem_attributes(void *vaddr, unsigned long size);
 
+bool sme_active(void);
+bool sev_active(void);
+
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask	0ULL
@@ -64,6 +67,9 @@ static inline void __init sme_early_init(void) { }
 static inline void __init sme_encrypt_kernel(void) { }
 static inline void __init sme_enable(struct boot_params *bp) { }
 
+static inline bool sme_active(void) { return false; }
+static inline bool sev_active(void) { return false; }
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 /*
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 3fcc8e01683b..b84c9a52df18 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -40,6 +40,8 @@ static char sme_cmdline_off[] __initdata = "off";
 u64 sme_me_mask __section(.data) = 0;
 EXPORT_SYMBOL_GPL(sme_me_mask);
 
+static bool sev_enabled __section(.data) = false;
+
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
@@ -190,6 +192,30 @@ void __init sme_early_init(void)
 		protection_map[i] = pgprot_encrypted(protection_map[i]);
 }
 
+/*
+ * SME and SEV are very similar but they are not the same, so there are
+ * times that the kernel will need to distinguish between SME and SEV. The
+ * sme_active() and sev_active() functions are used for this.  When a
+ * distinction isn't needed, the mem_encrypt_active() function can be used.
+ *
+ * The trampoline code is a good example for this requirement.  Before
+ * paging is activated, SME will access all memory as decrypted, but SEV
+ * will access all memory as encrypted.  So, when APs are being brought
+ * up under SME the trampoline area cannot be encrypted, whereas under SEV
+ * the trampoline area must be encrypted.
+ */
+bool sme_active(void)
+{
+	return sme_me_mask && !sev_enabled;
+}
+EXPORT_SYMBOL_GPL(sme_active);
+
+bool sev_active(void)
+{
+	return sme_me_mask && sev_enabled;
+}
+EXPORT_SYMBOL_GPL(sev_active);
+
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void)
 {
diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
index 265a9cd21cb4..b310a9c18113 100644
--- a/include/linux/mem_encrypt.h
+++ b/include/linux/mem_encrypt.h
@@ -23,11 +23,14 @@
 
 #define sme_me_mask	0ULL
 
+static inline bool sme_active(void) { return false; }
+static inline bool sev_active(void) { return false; }
+
 #endif	/* CONFIG_ARCH_HAS_MEM_ENCRYPT */
 
-static inline bool sme_active(void)
+static inline bool mem_encrypt_active(void)
 {
-	return !!sme_me_mask;
+	return sme_me_mask;
 }
 
 static inline u64 sme_get_me_mask(void)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [Part1 PATCH v5 18/18] x86/mm: add 'sme' argument in mem_encrypt=
  2017-09-28  9:02   ` Borislav Petkov
  2017-09-28 18:48     ` Brijesh Singh
  2017-09-29 21:27     ` [Part1 PATCH v5.1 " Brijesh Singh
@ 2017-09-29 23:06     ` Brijesh Singh
  2017-09-30 11:56       ` [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option Borislav Petkov
  2 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-29 23:06 UTC (permalink / raw)
  To: bp
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel, Tom Lendacky

The mem_encrypt=on activates both SME and SEV. Add a new argument to disable
the SEV and allow SME. The argument can be useful when SEV has issues and
we want to disable it.

early_detect_mem_encrypt() [cpu/amd.com] will need to know the state of
the mem_encrypt= argument. Since early_detect_mem_encrypt() is not defined
as __init hence we are not able to use the 'boot_command_line' variable to
parse the cmdline argument. We introduce a new function me_cmdline_state()
to get the cmdline state from mem_encrypt.c.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: kvm@vger.kernel.org
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
Boris,

The patch depends on "x86/CPU/AMD: Add the SEV CPU feature" from Part2 [1].

[1] https://patchwork.kernel.org/patch/9960315/

 Documentation/admin-guide/kernel-parameters.txt |  5 +++--
 arch/x86/include/asm/mem_encrypt.h              |  2 ++
 arch/x86/kernel/cpu/amd.c                       | 10 +++++++++
 arch/x86/mm/mem_encrypt.c                       | 27 +++++++++++++++++++++----
 include/linux/mem_encrypt.h                     |  7 +++++++
 5 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 05496622b4ef..811e0aca1c0b 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2238,8 +2238,9 @@
 			Default (depends on kernel configuration option):
 			  on  (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y)
 			  off (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=n)
-			mem_encrypt=on:		Activate SME
-			mem_encrypt=off:	Do not activate SME
+			mem_encrypt=on:		Activate SME and SEV
+			mem_encrypt=off:	Do not activate SME and SEV
+			mem_encrypt=sme:	Activate SME only
 
 			Refer to Documentation/x86/amd-memory-encryption.txt
 			for details on when memory encryption can be activated.
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 3ba68c92be1b..0f012ff9691d 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -52,6 +52,7 @@ void swiotlb_set_mem_attributes(void *vaddr, unsigned long size);
 
 bool sme_active(void);
 bool sev_active(void);
+unsigned int me_cmdline_state(void);
 
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
@@ -72,6 +73,7 @@ static inline void __init sme_enable(struct boot_params *bp) { }
 
 static inline bool sme_active(void) { return false; }
 static inline bool sev_active(void) { return false; }
+static inline unsigned int me_cmdline_state(void) { return ME_CMDLINE_OFF; }
 
 static inline int __init
 early_set_memory_decrypted(resource_size_t paddr, unsigned long size) { return 0; }
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index c1234aa0550c..10dfa7f1f34d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -592,6 +592,16 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
 		if (!(msr & MSR_K7_HWCR_SMMLOCK))
 			goto clear_sev;
 
+		/* Check for the mem_encrypt cmdline parameter and act accordingly. */
+		switch (me_cmdline_state()) {
+		case ME_CMDLINE_OFF:
+			goto clear_all;
+		case ME_CMDLINE_SME:
+			goto clear_sev;
+		default:
+			break;
+		}
+
 		return;
 
 clear_all:
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 057417a3d9b4..183cd481a55f 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -33,6 +33,7 @@
 static char sme_cmdline_arg[] __initdata = "mem_encrypt";
 static char sme_cmdline_on[]  __initdata = "on";
 static char sme_cmdline_off[] __initdata = "off";
+static char sme_cmdline_sme[] __initdata = "sme";
 
 /*
  * Since SME related variables are set early in the boot process they must
@@ -45,6 +46,7 @@ DEFINE_STATIC_KEY_FALSE(__sev);
 EXPORT_SYMBOL_GPL(__sev);
 
 static bool sev_enabled __section(.data) = false;
+static unsigned int cmdline_state __section(.data) = ME_CMDLINE_OFF;
 
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
@@ -403,6 +405,11 @@ bool sev_active(void)
 }
 EXPORT_SYMBOL_GPL(sev_active);
 
+unsigned int me_cmdline_state(void)
+{
+	return cmdline_state;
+}
+
 static const struct dma_map_ops sev_dma_ops = {
 	.alloc                  = sev_alloc,
 	.free                   = sev_free,
@@ -768,7 +775,7 @@ void __init sme_encrypt_kernel(void)
 
 void __init __nostackprotector sme_enable(struct boot_params *bp)
 {
-	const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
+	const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off, *cmdline_sme;
 	unsigned int eax, ebx, ecx, edx;
 	unsigned long feature_mask;
 	bool active_by_default;
@@ -842,6 +849,9 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 	asm ("lea sme_cmdline_off(%%rip), %0"
 	     : "=r" (cmdline_off)
 	     : "p" (sme_cmdline_off));
+	asm ("lea sme_cmdline_sme(%%rip), %0"
+	     : "=r" (cmdline_sme)
+	     : "p" (sme_cmdline_sme));
 
 	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
 		active_by_default = true;
@@ -853,10 +863,19 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 
 	cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
 
-	if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
+	if (!strncmp(buffer, cmdline_on, sizeof(buffer))) {
 		sme_me_mask = me_mask;
-	else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
+		cmdline_state = ME_CMDLINE_ON;
+	} else if (!strncmp(buffer, cmdline_off, sizeof(buffer))) {
 		sme_me_mask = 0;
-	else
+		cmdline_state = ME_CMDLINE_OFF;
+	} else if (!strncmp(buffer, cmdline_sme, sizeof(buffer))) {
+		sme_me_mask = me_mask;
+		cmdline_state = ME_CMDLINE_SME;
+	} else {
 		sme_me_mask = active_by_default ? me_mask : 0;
+		if (active_by_default)
+			cmdline_state = ME_CMDLINE_ON;
+	}
+
 }
diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
index b310a9c18113..7863cf2137e0 100644
--- a/include/linux/mem_encrypt.h
+++ b/include/linux/mem_encrypt.h
@@ -15,6 +15,12 @@
 
 #ifndef __ASSEMBLY__
 
+enum {
+	ME_CMDLINE_OFF,
+	ME_CMDLINE_ON,
+	ME_CMDLINE_SME
+};
+
 #ifdef CONFIG_ARCH_HAS_MEM_ENCRYPT
 
 #include <asm/mem_encrypt.h>
@@ -25,6 +31,7 @@
 
 static inline bool sme_active(void) { return false; }
 static inline bool sev_active(void) { return false; }
+static unsigned int me_cmdline_state(void) { return ME_CMDLINE_OFF; }
 
 #endif	/* CONFIG_ARCH_HAS_MEM_ENCRYPT */
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [Part1 PATCH v5.1 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support
  2017-09-29 21:27     ` [Part1 PATCH v5.1 " Brijesh Singh
@ 2017-09-30  8:49       ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-09-30  8:49 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Andy Lutomirski, linux-kernel, x86

On Fri, Sep 29, 2017 at 04:27:47PM -0500, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
> 
> Provide support for Secure Encrypted Virtualization (SEV). This initial
> support defines a flag that is used by the kernel to determine if it is
> running with SEV active.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: linux-kernel@vger.kernel.org
> Cc: x86@kernel.org
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> 
> Hi Boris,
> 
> Similar to the sme_me_mask, sev_enabled must live in .data section otherwise it
> will get zero'ed in clear_bss() and we will loose the value. I have encountered
> this issue when booting SEV guest using qemu's -kernel option.

Ah, good catch.

> I have removed your R-b since was not sure if you are still okay with the change.

Sure, looks good still.

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-09-29 23:06     ` [Part1 PATCH v5 18/18] x86/mm: add 'sme' argument in mem_encrypt= Brijesh Singh
@ 2017-09-30 11:56       ` Borislav Petkov
  2017-09-30 21:17         ` Brijesh Singh
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-09-30 11:56 UTC (permalink / raw)
  To: Brijesh Singh, Tom Lendacky
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Paolo Bonzini,
	Radim Krčmář,
	kvm, x86, linux-kernel

On Fri, Sep 29, 2017 at 06:06:52PM -0500, Brijesh Singh wrote:
> The mem_encrypt=on activates both SME and SEV. Add a new argument to disable
> the SEV and allow SME. The argument can be useful when SEV has issues and
> we want to disable it.
> 
> early_detect_mem_encrypt() [cpu/amd.com] will need to know the state of
> the mem_encrypt= argument. Since early_detect_mem_encrypt() is not defined
> as __init hence we are not able to use the 'boot_command_line' variable to
> parse the cmdline argument. We introduce a new function me_cmdline_state()
> to get the cmdline state from mem_encrypt.c.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: "Radim Krčmář" <rkrcmar@redhat.com>
> Cc: Borislav Petkov <bp@suse.de>
> Cc: kvm@vger.kernel.org
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---

Ok, I went and simplified this whole code path a bit because it was
needlessly a bit too complex. Below is the result, only compile-tested.

Brijesh, Tom, guys, please check my logic, I might've missed a case.

Thanks.

---
From: Borislav Petkov <bp@suse.de>
Date: Sat, 30 Sep 2017 13:33:26 +0200
Subject: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option

Extend the mem_encrypt= cmdline option with the "sme" argument so that
one can enable SME only (i.e., this serves as a SEV chicken bit). While
at it, streamline and document the flow logic here:

1. Check whether the SME CPUID leaf is present

2. Check whether the HW has enabled SME/SEV

3. Only *then* look at any potential command line params because doing
so before is pointless.

3.1 mem_encrypt=on  - enable both SME/SEV
3.2 mem_encrypt=sme - enable only SME
3.3 mem_encrypt=off - disable both

In addition, CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT enables both if
the kernel is built with it enabled.

While at it, shorten variable names, simplify code flow.

This is based on a patch by Brijesh Singh <brijesh.singh@amd.com>.

Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: kvm@vger.kernel.org
Cc: x86@kernel.org
---
 arch/x86/include/asm/mem_encrypt.h |  2 +
 arch/x86/kernel/cpu/amd.c          |  6 +++
 arch/x86/mm/mem_encrypt.c          | 82 +++++++++++++++++++-------------------
 3 files changed, 49 insertions(+), 41 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 3ba68c92be1b..175310f00202 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -19,6 +19,8 @@
 
 #include <asm/bootparam.h>
 
+extern bool sev_enabled;
+
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern u64 sme_me_mask;
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index c1234aa0550c..d0669f3966a6 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -13,6 +13,7 @@
 #include <asm/smp.h>
 #include <asm/pci-direct.h>
 #include <asm/delay.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_X86_64
 # include <asm/mmconfig.h>
@@ -32,6 +33,8 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
  */
 static u32 nodes_per_socket = 1;
 
+bool sev_enabled __section(.data) = false;
+
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
 	u32 gprs[8] = { 0 };
@@ -588,6 +591,9 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
 		if (IS_ENABLED(CONFIG_X86_32))
 			goto clear_all;
 
+		if (!sev_enabled)
+			goto clear_sev;
+
 		rdmsrl(MSR_K7_HWCR, msr);
 		if (!(msr & MSR_K7_HWCR_SMMLOCK))
 			goto clear_sev;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 057417a3d9b4..9b83bc1be7c0 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -27,12 +27,14 @@
 #include <asm/processor-flags.h>
 #include <asm/msr.h>
 #include <asm/cmdline.h>
+#include <asm/mem_encrypt.h>
 
 #include "mm_internal.h"
 
-static char sme_cmdline_arg[] __initdata = "mem_encrypt";
-static char sme_cmdline_on[]  __initdata = "on";
-static char sme_cmdline_off[] __initdata = "off";
+static char sme_cmd[] __initdata = "mem_encrypt";
+static char sme_cmd_on[]  __initdata = "on";
+static char sme_cmd_off[] __initdata = "off";
+static char sme_cmd_sme[] __initdata = "sme";
 
 /*
  * Since SME related variables are set early in the boot process they must
@@ -44,8 +46,6 @@ EXPORT_SYMBOL_GPL(sme_me_mask);
 DEFINE_STATIC_KEY_FALSE(__sev);
 EXPORT_SYMBOL_GPL(__sev);
 
-static bool sev_enabled __section(.data) = false;
-
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
@@ -768,13 +768,13 @@ void __init sme_encrypt_kernel(void)
 
 void __init __nostackprotector sme_enable(struct boot_params *bp)
 {
-	const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
+	const char *cmdline_ptr, *cmd, *cmd_on, *cmd_off, *cmd_sme;
 	unsigned int eax, ebx, ecx, edx;
 	unsigned long feature_mask;
-	bool active_by_default;
-	unsigned long me_mask;
+	u64 me_mask, msr;
 	char buffer[16];
-	u64 msr;
+	bool sme_only;
+	int ret;
 
 	/* Check for the SME/SEV support leaf */
 	eax = 0x80000000;
@@ -808,55 +808,55 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 	if (!(eax & feature_mask))
 		return;
 
-	me_mask = 1UL << (ebx & 0x3f);
-
-	/* Check if memory encryption is enabled */
+	/* For SME, check the SYSCFG MSR */
 	if (feature_mask == AMD_SME_BIT) {
-		/* For SME, check the SYSCFG MSR */
 		msr = __rdmsr(MSR_K8_SYSCFG);
 		if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
 			return;
-	} else {
-		/* For SEV, check the SEV MSR */
+	}
+
+	/* For SEV, check the SEV MSR */
+	if (feature_mask == AMD_SEV_BIT) {
 		msr = __rdmsr(MSR_AMD64_SEV);
 		if (!(msr & MSR_AMD64_SEV_ENABLED))
 			return;
-
-		/* SEV state cannot be controlled by a command line option */
-		sme_me_mask = me_mask;
-		sev_enabled = true;
-		return;
 	}
 
+	me_mask = BIT_ULL(ebx & 0x3f);
+
 	/*
 	 * Fixups have not been applied to phys_base yet and we're running
 	 * identity mapped, so we must obtain the address to the SME command
 	 * line argument data using rip-relative addressing.
 	 */
-	asm ("lea sme_cmdline_arg(%%rip), %0"
-	     : "=r" (cmdline_arg)
-	     : "p" (sme_cmdline_arg));
-	asm ("lea sme_cmdline_on(%%rip), %0"
-	     : "=r" (cmdline_on)
-	     : "p" (sme_cmdline_on));
-	asm ("lea sme_cmdline_off(%%rip), %0"
-	     : "=r" (cmdline_off)
-	     : "p" (sme_cmdline_off));
-
-	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
-		active_by_default = true;
-	else
-		active_by_default = false;
+	asm ("lea sme_cmd(%%rip), %0"	  : "=r" (cmd)	   : "p" (sme_cmd));
+	asm ("lea sme_cmd_on(%%rip), %0"  : "=r" (cmd_on)  : "p" (sme_cmd_on));
+	asm ("lea sme_cmd_off(%%rip), %0" : "=r" (cmd_off) : "p" (sme_cmd_off));
+	asm ("lea sme_cmd_sme(%%rip), %0" : "=r" (cmd_sme) : "p" (sme_cmd_sme));
 
 	cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
-				     ((u64)bp->ext_cmd_line_ptr << 32));
+				    ((u64)bp->ext_cmd_line_ptr << 32));
 
-	cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
+	ret = cmdline_find_option(cmdline_ptr, cmd, buffer, sizeof(buffer));
+	if (ret < 0)
+		return;
 
-	if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
-		sme_me_mask = me_mask;
-	else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
+	if (!strncmp(buffer, cmd_off, sizeof(buffer))) {
 		sme_me_mask = 0;
-	else
-		sme_me_mask = active_by_default ? me_mask : 0;
+		return;
+	} else if (!strncmp(buffer, cmd_on, sizeof(buffer))) {
+		sme_me_mask = me_mask;
+	} else if (!strncmp(buffer, cmd_sme, sizeof(buffer))) {
+		sme_only = true;
+	}
+
+	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
+		sme_me_mask = me_mask;
+
+	if (sme_only)
+		return;
+
+	/* For SEV, check the SEV MSR */
+	if (feature_mask == AMD_SEV_BIT)
+		sev_enabled = true;
 }
-- 
2.13.0

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-09-30 11:56       ` [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option Borislav Petkov
@ 2017-09-30 21:17         ` Brijesh Singh
  2017-09-30 21:41           ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-09-30 21:17 UTC (permalink / raw)
  To: Borislav Petkov, Tom Lendacky
  Cc: brijesh.singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel



On 9/30/17 6:56 AM, Borislav Petkov wrote:
...
> Ok, I went and simplified this whole code path a bit because it was
> needlessly a bit too complex. Below is the result, only compile-tested.
>
> Brijesh, Tom, guys, please check my logic, I might've missed a case.

I will take a closure look at this patch on Monday but at a glance I am
not sure if patch is addressing our main issue. We were trying to limit
the SEV feature exposure from the host OS. The current logic is:

1. Check whether the SME CPUID leaf is present

2. Check if we are running under hypervisor

3. If we are running under hypervisor, check SME_ENABLED bit in
MSR_AMD64_SEV

3.1 If bit is cleared, its non SEV guest. Return from the function.

3.2 If bit is set, its SEV guest. We set sev_enabled to 'true' and also
set 'sme_me_mask'. Return from the function.
The SEV state *cannot* be controlled by a command line option.

4. We are booted on bare-metal. Check if memory encryption is enabled.
if enabled, look at any potential command line.

Please see the sme_enable() from mem_encrypt.c [1].

https://github.com/codomania/tip/blob/sev-v5-p1/arch/x86/mm/mem_encrypt.c

Thanks
Brijesh

> Thanks.
>
> ---
> From: Borislav Petkov <bp@suse.de>
> Date: Sat, 30 Sep 2017 13:33:26 +0200
> Subject: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
>
> Extend the mem_encrypt= cmdline option with the "sme" argument so that
> one can enable SME only (i.e., this serves as a SEV chicken bit). While
> at it, streamline and document the flow logic here:
>
> 1. Check whether the SME CPUID leaf is present
>
> 2. Check whether the HW has enabled SME/SEV
>
> 3. Only *then* look at any potential command line params because doing
> so before is pointless.
>
> 3.1 mem_encrypt=on  - enable both SME/SEV
> 3.2 mem_encrypt=sme - enable only SME
> 3.3 mem_encrypt=off - disable both
>
> In addition, CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT enables both if
> the kernel is built with it enabled.
>
> While at it, shorten variable names, simplify code flow.
>
> This is based on a patch by Brijesh Singh <brijesh.singh@amd.com>.
>
> Signed-off-by: Borislav Petkov <bp@suse.de>
> Cc: Brijesh Singh <brijesh.singh@amd.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: kvm@vger.kernel.org
> Cc: x86@kernel.org
> ---
>  arch/x86/include/asm/mem_encrypt.h |  2 +
>  arch/x86/kernel/cpu/amd.c          |  6 +++
>  arch/x86/mm/mem_encrypt.c          | 82 +++++++++++++++++++-------------------
>  3 files changed, 49 insertions(+), 41 deletions(-)
>
> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
> index 3ba68c92be1b..175310f00202 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -19,6 +19,8 @@
>  
>  #include <asm/bootparam.h>
>  
> +extern bool sev_enabled;
> +
>  #ifdef CONFIG_AMD_MEM_ENCRYPT
>  
>  extern u64 sme_me_mask;
> diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
> index c1234aa0550c..d0669f3966a6 100644
> --- a/arch/x86/kernel/cpu/amd.c
> +++ b/arch/x86/kernel/cpu/amd.c
> @@ -13,6 +13,7 @@
>  #include <asm/smp.h>
>  #include <asm/pci-direct.h>
>  #include <asm/delay.h>
> +#include <asm/mem_encrypt.h>
>  
>  #ifdef CONFIG_X86_64
>  # include <asm/mmconfig.h>
> @@ -32,6 +33,8 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
>   */
>  static u32 nodes_per_socket = 1;
>  
> +bool sev_enabled __section(.data) = false;
> +
>  static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
>  {
>  	u32 gprs[8] = { 0 };
> @@ -588,6 +591,9 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
>  		if (IS_ENABLED(CONFIG_X86_32))
>  			goto clear_all;
>  
> +		if (!sev_enabled)
> +			goto clear_sev;
> +
>  		rdmsrl(MSR_K7_HWCR, msr);
>  		if (!(msr & MSR_K7_HWCR_SMMLOCK))
>  			goto clear_sev;
> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 057417a3d9b4..9b83bc1be7c0 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -27,12 +27,14 @@
>  #include <asm/processor-flags.h>
>  #include <asm/msr.h>
>  #include <asm/cmdline.h>
> +#include <asm/mem_encrypt.h>
>  
>  #include "mm_internal.h"
>  
> -static char sme_cmdline_arg[] __initdata = "mem_encrypt";
> -static char sme_cmdline_on[]  __initdata = "on";
> -static char sme_cmdline_off[] __initdata = "off";
> +static char sme_cmd[] __initdata = "mem_encrypt";
> +static char sme_cmd_on[]  __initdata = "on";
> +static char sme_cmd_off[] __initdata = "off";
> +static char sme_cmd_sme[] __initdata = "sme";
>  
>  /*
>   * Since SME related variables are set early in the boot process they must
> @@ -44,8 +46,6 @@ EXPORT_SYMBOL_GPL(sme_me_mask);
>  DEFINE_STATIC_KEY_FALSE(__sev);
>  EXPORT_SYMBOL_GPL(__sev);
>  
> -static bool sev_enabled __section(.data) = false;
> -
>  /* Buffer used for early in-place encryption by BSP, no locking needed */
>  static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
>  
> @@ -768,13 +768,13 @@ void __init sme_encrypt_kernel(void)
>  
>  void __init __nostackprotector sme_enable(struct boot_params *bp)
>  {
> -	const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
> +	const char *cmdline_ptr, *cmd, *cmd_on, *cmd_off, *cmd_sme;
>  	unsigned int eax, ebx, ecx, edx;
>  	unsigned long feature_mask;
> -	bool active_by_default;
> -	unsigned long me_mask;
> +	u64 me_mask, msr;
>  	char buffer[16];
> -	u64 msr;
> +	bool sme_only;
> +	int ret;
>  
>  	/* Check for the SME/SEV support leaf */
>  	eax = 0x80000000;
> @@ -808,55 +808,55 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
>  	if (!(eax & feature_mask))
>  		return;
>  
> -	me_mask = 1UL << (ebx & 0x3f);
> -
> -	/* Check if memory encryption is enabled */
> +	/* For SME, check the SYSCFG MSR */
>  	if (feature_mask == AMD_SME_BIT) {
> -		/* For SME, check the SYSCFG MSR */
>  		msr = __rdmsr(MSR_K8_SYSCFG);
>  		if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
>  			return;
> -	} else {
> -		/* For SEV, check the SEV MSR */
> +	}
> +
> +	/* For SEV, check the SEV MSR */
> +	if (feature_mask == AMD_SEV_BIT) {
>  		msr = __rdmsr(MSR_AMD64_SEV);
>  		if (!(msr & MSR_AMD64_SEV_ENABLED))
>  			return;
> -
> -		/* SEV state cannot be controlled by a command line option */
> -		sme_me_mask = me_mask;
> -		sev_enabled = true;
> -		return;
>  	}
>  
> +	me_mask = BIT_ULL(ebx & 0x3f);
> +
>  	/*
>  	 * Fixups have not been applied to phys_base yet and we're running
>  	 * identity mapped, so we must obtain the address to the SME command
>  	 * line argument data using rip-relative addressing.
>  	 */
> -	asm ("lea sme_cmdline_arg(%%rip), %0"
> -	     : "=r" (cmdline_arg)
> -	     : "p" (sme_cmdline_arg));
> -	asm ("lea sme_cmdline_on(%%rip), %0"
> -	     : "=r" (cmdline_on)
> -	     : "p" (sme_cmdline_on));
> -	asm ("lea sme_cmdline_off(%%rip), %0"
> -	     : "=r" (cmdline_off)
> -	     : "p" (sme_cmdline_off));
> -
> -	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
> -		active_by_default = true;
> -	else
> -		active_by_default = false;
> +	asm ("lea sme_cmd(%%rip), %0"	  : "=r" (cmd)	   : "p" (sme_cmd));
> +	asm ("lea sme_cmd_on(%%rip), %0"  : "=r" (cmd_on)  : "p" (sme_cmd_on));
> +	asm ("lea sme_cmd_off(%%rip), %0" : "=r" (cmd_off) : "p" (sme_cmd_off));
> +	asm ("lea sme_cmd_sme(%%rip), %0" : "=r" (cmd_sme) : "p" (sme_cmd_sme));
>  
>  	cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
> -				     ((u64)bp->ext_cmd_line_ptr << 32));
> +				    ((u64)bp->ext_cmd_line_ptr << 32));
>  
> -	cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
> +	ret = cmdline_find_option(cmdline_ptr, cmd, buffer, sizeof(buffer));
> +	if (ret < 0)
> +		return;
>  
> -	if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
> -		sme_me_mask = me_mask;
> -	else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
> +	if (!strncmp(buffer, cmd_off, sizeof(buffer))) {
>  		sme_me_mask = 0;
> -	else
> -		sme_me_mask = active_by_default ? me_mask : 0;
> +		return;
> +	} else if (!strncmp(buffer, cmd_on, sizeof(buffer))) {
> +		sme_me_mask = me_mask;
> +	} else if (!strncmp(buffer, cmd_sme, sizeof(buffer))) {
> +		sme_only = true;
> +	}
> +
> +	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
> +		sme_me_mask = me_mask;
> +
> +	if (sme_only)
> +		return;
> +
> +	/* For SEV, check the SEV MSR */
> +	if (feature_mask == AMD_SEV_BIT)
> +		sev_enabled = true;
>  }

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-09-30 21:17         ` Brijesh Singh
@ 2017-09-30 21:41           ` Borislav Petkov
  2017-10-01 17:00             ` Brijesh Singh
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-09-30 21:41 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel

On Sat, Sep 30, 2017 at 04:17:39PM -0500, Brijesh Singh wrote:
> I will take a closure look at this patch on Monday but at a glance I am
> not sure if patch is addressing our main issue. We were trying to limit
> the SEV feature exposure from the host OS. The current logic is:
> 
> 1. Check whether the SME CPUID leaf is present

Check.

> 2. Check if we are running under hypervisor

Check.

> 3. If we are running under hypervisor, check SME_ENABLED bit in
> MSR_AMD64_SEV

Check.

> 3.1 If bit is cleared, its non SEV guest. Return from the function.

Check.

> 3.2 If bit is set, its SEV guest. We set sev_enabled to 'true' and also
> set 'sme_me_mask'. Return from the function.
> The SEV state *cannot* be controlled by a command line option.

So how do you propose to disable SEV? Right now I do:

        if (feature_mask == AMD_SEV_BIT)
                sev_enabled = true;

at the end, when mem_encrypt=sme wasn't supplied on the cmdline. IOW,
SEV is enabled either when CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT or
mem_encrypt=on.

Hmmm?

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-09-30 21:41           ` Borislav Petkov
@ 2017-10-01 17:00             ` Brijesh Singh
  2017-10-01 17:16               ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-10-01 17:00 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: brijesh.singh, Tom Lendacky, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel



On 9/30/17 4:41 PM, Borislav Petkov wrote:

...
>> 3.2 If bit is set, its SEV guest. We set sev_enabled to 'true' and also
>> set 'sme_me_mask'. Return from the function.
>> The SEV state *cannot* be controlled by a command line option.
> So how do you propose to disable SEV? Right now I do:
>
>         if (feature_mask == AMD_SEV_BIT)
>                 sev_enabled = true;

Host OS:
--------
We can control the SEV feature visibility to the hypervisor through the
host OS command line.

mem_encrypt=on -   SEV feature is available
mem_encrypt=sme - SEV feature is disabled  
mem_encrypt =off -  SEV feature is disabled

When SEV feature is disabled, KVM will not be able to launch any SEV
guests.  When SEV support is available, KVM can enable it in a specific
VM by setting SEV bit before executing the VMRUN instruction.

Guest OS:
--------
Checks the MSR_AMD64_SEV to determine if SEV feature is enabled. Please
note that the MSR is a read-only. IOW, MSR is not intercepted by the
hypervisor.

Currently, mem_encrypt=xxx and CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
is don't care. We can not depend on the command line because when SEV is
enabled in a VM then instruction fetch will be decrypted by the
hardware. If we want then we can perform the comparison between the SEV
state obtained through MSR with user supplied command line and trigger
BUG() if they don't match.


> at the end, when mem_encrypt=sme wasn't supplied on the cmdline. IOW,
> SEV is enabled either when CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT or
> mem_encrypt=on.
>
> Hmmm?
>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-01 17:00             ` Brijesh Singh
@ 2017-10-01 17:16               ` Borislav Petkov
  2017-10-01 19:45                 ` Brijesh Singh
  2017-10-02 13:44                 ` Tom Lendacky
  0 siblings, 2 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-10-01 17:16 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Tom Lendacky, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel

On Sun, Oct 01, 2017 at 12:00:31PM -0500, Brijesh Singh wrote:
> When SEV feature is disabled, KVM will not be able to launch any SEV
> guests.  When SEV support is available, KVM can enable it in a specific
> VM by setting SEV bit before executing the VMRUN instruction.

So I want to be able to disable SEV and the whole code that comes with
it in the *host*.

> Guest OS:
> --------
> Checks the MSR_AMD64_SEV to determine if SEV feature is enabled. Please
> note that the MSR is a read-only. IOW, MSR is not intercepted by the
> hypervisor.
> 
> Currently, mem_encrypt=xxx and CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
> is don't care. We can not depend on the command line because when SEV is
> enabled in a VM then instruction fetch will be decrypted by the
> hardware. If we want then we can perform the comparison between the SEV
> state obtained through MSR with user supplied command line and trigger
> BUG() if they don't match.

And when we have supplied mem_encrypt=sme to the *host* cmdline, it
should be impossible to start SEV guests. IOW, that feature mask test
should not happen and I should do instead:

        } else if (!strncmp(buffer, cmd_sme, sizeof(buffer))) {
                sme_only = true;
		sev_enabled = false;
        }

Or, respectively, not set it here as it is false already but set it at
the end of the function like this:

        if (sme_only)
                return;

	sev_enabled = true;
}

Hmmm?

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-01 17:16               ` Borislav Petkov
@ 2017-10-01 19:45                 ` Brijesh Singh
  2017-10-01 22:02                   ` Borislav Petkov
  2017-10-02 13:44                 ` Tom Lendacky
  1 sibling, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-10-01 19:45 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Paolo Bonzini,
	Radim Krčmář,
	kvm, x86, linux-kernel, Brijesh Singh

>
> So I want to be able to disable SEV and the whole code that comes with
> it in the *host*.

We can add a new variable 'sme_only'. By default this variable should be set
to false. When mem_encrypt=sme is passed then set it to true and
based on sme_only state early_detect_mem_encrypt() can clear X86_FEATURE_SEV
flag.

Here are the changes on top of your patch. I did a quick test in both host and
guest OS and it seems to be working okay. In host OS mem_encrypt=sme disabled
the SEV but in guest its still don't care. I will do more test later...

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 175310f00202..73a6fb3b14a1 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -19,7 +19,7 @@
 
 #include <asm/bootparam.h>
 
-extern bool sev_enabled;
+extern bool sme_only;
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index d0669f3966a6..a09b02959874 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -33,7 +33,7 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
  */
 static u32 nodes_per_socket = 1;
 
-bool sev_enabled __section(.data) = false;
+bool sme_only __section(.data) = false;
 
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
@@ -591,7 +591,7 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
 		if (IS_ENABLED(CONFIG_X86_32))
 			goto clear_all;
 
-		if (!sev_enabled)
+		if (sme_only)
 			goto clear_sev;
 
 		rdmsrl(MSR_K7_HWCR, msr);
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 9b83bc1be7c0..a135e4497021 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -45,6 +45,7 @@ u64 sme_me_mask __section(.data) = 0;
 EXPORT_SYMBOL_GPL(sme_me_mask);
 DEFINE_STATIC_KEY_FALSE(__sev);
 EXPORT_SYMBOL_GPL(__sev);
+static bool sev_enabled __section(.data) = false;
 
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
@@ -773,7 +774,6 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 	unsigned long feature_mask;
 	u64 me_mask, msr;
 	char buffer[16];
-	bool sme_only;
 	int ret;
 
 	/* Check for the SME/SEV support leaf */
@@ -808,6 +808,8 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 	if (!(eax & feature_mask))
 		return;
 
+	me_mask = BIT_ULL(ebx & 0x3f);
+
 	/* For SME, check the SYSCFG MSR */
 	if (feature_mask == AMD_SME_BIT) {
 		msr = __rdmsr(MSR_K8_SYSCFG);
@@ -820,9 +822,13 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 		msr = __rdmsr(MSR_AMD64_SEV);
 		if (!(msr & MSR_AMD64_SEV_ENABLED))
 			return;
-	}
 
-	me_mask = BIT_ULL(ebx & 0x3f);
+		if (feature_mask == AMD_SEV_BIT) {
+			sme_me_mask = me_mask;
+			sev_enabled = true;
+			return;
+		}
+	}
 
 	/*
 	 * Fixups have not been applied to phys_base yet and we're running
@@ -847,16 +853,11 @@ void __init __nostackprotector sme_enable(struct boot_params *bp)
 	} else if (!strncmp(buffer, cmd_on, sizeof(buffer))) {
 		sme_me_mask = me_mask;
 	} else if (!strncmp(buffer, cmd_sme, sizeof(buffer))) {
+		sme_me_mask = me_mask;
 		sme_only = true;
+		return;
 	}
 
 	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
 		sme_me_mask = me_mask;
-
-	if (sme_only)
-		return;
-
-	/* For SEV, check the SEV MSR */
-	if (feature_mask == AMD_SEV_BIT)
-		sev_enabled = true;
 }
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-01 19:45                 ` Brijesh Singh
@ 2017-10-01 22:02                   ` Borislav Petkov
  2017-10-02 11:32                     ` Brijesh Singh
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-10-01 22:02 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Paolo Bonzini,
	Radim Krčmář,
	kvm, x86, linux-kernel

On Sun, Oct 01, 2017 at 02:45:09PM -0500, Brijesh Singh wrote:
> >
> > So I want to be able to disable SEV and the whole code that comes with
> > it in the *host*.
> 
> We can add a new variable 'sme_only'. By default this variable should be set
> to false. When mem_encrypt=sme is passed then set it to true and
> based on sme_only state early_detect_mem_encrypt() can clear X86_FEATURE_SEV
> flag.

Why would you need yet another variable? We have sev_enabled already?!?

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-01 22:02                   ` Borislav Petkov
@ 2017-10-02 11:32                     ` Brijesh Singh
  2017-10-02 12:41                       ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-10-02 11:32 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: brijesh.singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel



On 10/1/17 5:02 PM, Borislav Petkov wrote:
> On Sun, Oct 01, 2017 at 02:45:09PM -0500, Brijesh Singh wrote:
>>> So I want to be able to disable SEV and the whole code that comes with
>>> it in the *host*.
>> We can add a new variable 'sme_only'. By default this variable should be set
>> to false. When mem_encrypt=sme is passed then set it to true and
>> based on sme_only state early_detect_mem_encrypt() can clear X86_FEATURE_SEV
>> flag.
> Why would you need yet another variable? We have sev_enabled already?!?


Because sev_enabled will always be 'false' when we are booting on bare
metal. Whereas when we are running under hypervisor then this variable
will be true for the SEV guest, please see [1]. Both sev_active() and
sme_active() make use of this variable hence we will not be able to set
the sev_enabled variable on bare metal. Basically none of the SEV cases
will be executed on bare metal -- only thing which we need to take care
of is clearing the X86_FEATURE_SEV flag so that hypervisor will never
launch SEV guest when mem_encrypt=sme option is provided.


[1] https://marc.info/?l=linux-kernel&m=150672050612826&w=2

>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-02 11:32                     ` Brijesh Singh
@ 2017-10-02 12:41                       ` Borislav Petkov
  2017-10-02 15:07                         ` Brijesh Singh
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-10-02 12:41 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Paolo Bonzini,
	Radim Krčmář,
	kvm, x86, linux-kernel

On Mon, Oct 02, 2017 at 06:32:18AM -0500, Brijesh Singh wrote:
> Because sev_enabled will always be 'false' when we are booting on bare
> metal. Whereas when we are running under hypervisor then this variable
> will be true for the SEV guest, please see [1].

Ok, then. This needs absolutely to be documented. Please add a comment
over sev_enabled's definition.

> Both sev_active() and sme_active() make use of this variable
> hence we will not be able to set the sev_enabled variable on bare
> metal. Basically none of the SEV cases will be executed on bare
> metal -- only thing which we need to take care of is clearing the
> X86_FEATURE_SEV flag so that hypervisor will never launch SEV guest
> when mem_encrypt=sme option is provided.

In that case, you want to disable SEV at the guest loading point,
i.e., sev_guest_init() AFAICT is the earliest time we start prepping
a SEV guest. You can add a __setup() early param which parses
"mem_encrypt=sme", to arch/x86/kernel/cpu/amd.c and which sets a
sev_host_enabled bool or so. sev_guest_init() can then check that
variable before going any further. No need for any of that early parsing
changes.

I'll send a patch with the rest of my cleanups ontop of yours later.

Thx.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-01 17:16               ` Borislav Petkov
  2017-10-01 19:45                 ` Brijesh Singh
@ 2017-10-02 13:44                 ` Tom Lendacky
  2017-10-02 13:51                   ` Borislav Petkov
  1 sibling, 1 reply; 55+ messages in thread
From: Tom Lendacky @ 2017-10-02 13:44 UTC (permalink / raw)
  To: Borislav Petkov, Brijesh Singh
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Paolo Bonzini,
	Radim Krčmář,
	kvm, x86, linux-kernel

On 10/1/2017 12:16 PM, Borislav Petkov wrote:
> On Sun, Oct 01, 2017 at 12:00:31PM -0500, Brijesh Singh wrote:
>> When SEV feature is disabled, KVM will not be able to launch any SEV
>> guests.  When SEV support is available, KVM can enable it in a specific
>> VM by setting SEV bit before executing the VMRUN instruction.
> 
> So I want to be able to disable SEV and the whole code that comes with
> it in the *host*.

The ability to launch an SEV guest from the host is controlled by the SEV
feature bit.  When that is cleared (which happens in cpu/amd.c), then the
host will not be able to launch any SEV guests.

The confusion may come from the variable name.  The name sev_enabled
should probably be changed to sev_active since this variable is used as
follows:

   sme_me_mask == 0 			=> Neither SME nor SEV is active
   sme_me_mask != 0 && !sev_enabled	=> SME is active (host mode)
   sme_me_mask != 0 && sev_enabled	=> SEV is active (guest mode)

> 
>> Guest OS:
>> --------
>> Checks the MSR_AMD64_SEV to determine if SEV feature is enabled. Please
>> note that the MSR is a read-only. IOW, MSR is not intercepted by the
>> hypervisor.
>>
>> Currently, mem_encrypt=xxx and CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
>> is don't care. We can not depend on the command line because when SEV is
>> enabled in a VM then instruction fetch will be decrypted by the
>> hardware. If we want then we can perform the comparison between the SEV
>> state obtained through MSR with user supplied command line and trigger
>> BUG() if they don't match.
> 
> And when we have supplied mem_encrypt=sme to the *host* cmdline, it
> should be impossible to start SEV guests. IOW, that feature mask test
> should not happen and I should do instead:

I think we're talking about the same thing.  You want sev_enabled to
indicate whether you can launch an SEV guest.  We would still need an
sev_active variable to distinguish between SME and SEV during kernel
execution when the sme_me_mask is non-zero.  Currently, the SEV feature
bit acts as "sev_enabled" and the sev_enabled variable acts as
"sev_active" in this scenario.

Thanks,
Tom

> 
>          } else if (!strncmp(buffer, cmd_sme, sizeof(buffer))) {
>                  sme_only = true;
> 		sev_enabled = false;
>          }
> 
> Or, respectively, not set it here as it is false already but set it at
> the end of the function like this:
> 
>          if (sme_only)
>                  return;
> 
> 	sev_enabled = true;
> }
> 
> Hmmm?
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-02 13:44                 ` Tom Lendacky
@ 2017-10-02 13:51                   ` Borislav Petkov
  2017-10-02 16:35                     ` Tom Lendacky
  0 siblings, 1 reply; 55+ messages in thread
From: Borislav Petkov @ 2017-10-02 13:51 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel

On Mon, Oct 02, 2017 at 08:44:21AM -0500, Tom Lendacky wrote:
> I think we're talking about the same thing.  You want sev_enabled to
> indicate whether you can launch an SEV guest.  We would still need an
> sev_active variable to distinguish between SME and SEV during kernel
> execution when the sme_me_mask is non-zero.  Currently, the SEV feature
> bit acts as "sev_enabled" and the sev_enabled variable acts as
> "sev_active" in this scenario.

See my last email about sev_host_enabled. Does that sound better?

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-02 12:41                       ` Borislav Petkov
@ 2017-10-02 15:07                         ` Brijesh Singh
  2017-10-03 10:50                           ` Paolo Bonzini
  0 siblings, 1 reply; 55+ messages in thread
From: Brijesh Singh @ 2017-10-02 15:07 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: brijesh.singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel



On 10/02/2017 07:41 AM, Borislav Petkov wrote:
> On Mon, Oct 02, 2017 at 06:32:18AM -0500, Brijesh Singh wrote:
>> Because sev_enabled will always be 'false' when we are booting on bare
>> metal. Whereas when we are running under hypervisor then this variable
>> will be true for the SEV guest, please see [1].
> 
> Ok, then. This needs absolutely to be documented. Please add a comment
> over sev_enabled's definition.
> 
>> Both sev_active() and sme_active() make use of this variable
>> hence we will not be able to set the sev_enabled variable on bare
>> metal. Basically none of the SEV cases will be executed on bare
>> metal -- only thing which we need to take care of is clearing the
>> X86_FEATURE_SEV flag so that hypervisor will never launch SEV guest
>> when mem_encrypt=sme option is provided.
> 
> In that case, you want to disable SEV at the guest loading point,
> i.e., sev_guest_init() AFAICT is the earliest time we start prepping
> a SEV guest. You can add a __setup() early param which parses
> "mem_encrypt=sme", to arch/x86/kernel/cpu/amd.c and which sets a
> sev_host_enabled bool or so. sev_guest_init() can then check that
> variable before going any further. No need for any of that early parsing
> changes.


Yep, that will work just fine. There are couple of ways we can limit
hypervisor from creating the SEV guest 1) clear the X86_FEATURE_SEV bit
when mem_encrypt=sme is passed or 2) parse the mem_encrypt=xxx in kvm-amd.ko
and fail the KVM_SEV_INIT when mem_encrpt=sme or mem_encrypt=off.

I was not sure which way to go. We can go with #2 and kvm folks have any
concern then we can go back to #1. I will update KVM_SEV_INIT patch and
send you v4.1.

-Brijesh

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-02 13:51                   ` Borislav Petkov
@ 2017-10-02 16:35                     ` Tom Lendacky
  2017-10-03 11:29                       ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Tom Lendacky @ 2017-10-02 16:35 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel

On 10/2/2017 8:51 AM, Borislav Petkov wrote:
> On Mon, Oct 02, 2017 at 08:44:21AM -0500, Tom Lendacky wrote:
>> I think we're talking about the same thing.  You want sev_enabled to
>> indicate whether you can launch an SEV guest.  We would still need an
>> sev_active variable to distinguish between SME and SEV during kernel
>> execution when the sme_me_mask is non-zero.  Currently, the SEV feature
>> bit acts as "sev_enabled" and the sev_enabled variable acts as
>> "sev_active" in this scenario.
> 
> See my last email about sev_host_enabled. Does that sound better?

Hmmm... strange, I haven't received that email or that part of the thread
for that matter - including Brijesh's reply.  I'll talk with Brijesh and
let him run with it.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-02 15:07                         ` Brijesh Singh
@ 2017-10-03 10:50                           ` Paolo Bonzini
  2017-10-03 11:20                             ` Borislav Petkov
  0 siblings, 1 reply; 55+ messages in thread
From: Paolo Bonzini @ 2017-10-03 10:50 UTC (permalink / raw)
  To: Brijesh Singh, Borislav Petkov
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Radim Krčmář,
	kvm, x86, linux-kernel

On 02/10/2017 17:07, Brijesh Singh wrote:
> 
> 
> Yep, that will work just fine. There are couple of ways we can limit
> hypervisor from creating the SEV guest 1) clear the X86_FEATURE_SEV bit
> when mem_encrypt=sme is passed or 2) parse the mem_encrypt=xxx in
> kvm-amd.ko
> and fail the KVM_SEV_INIT when mem_encrpt=sme or mem_encrypt=off.

Stupid question ahead: if it's just about guests, why bother with
mem_encrypt=xxx at all?  kvm_amd should have a sev parameter anyway, you
can just do kvm_amd.sev=0 to disable it.

Paolo

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-03 10:50                           ` Paolo Bonzini
@ 2017-10-03 11:20                             ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-10-03 11:20 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Radim Krčmář,
	kvm, x86, linux-kernel

On Tue, Oct 03, 2017 at 12:50:15PM +0200, Paolo Bonzini wrote:
> Stupid question ahead: if it's just about guests, why bother with
> mem_encrypt=xxx at all?  kvm_amd should have a sev parameter anyway, you
> can just do kvm_amd.sev=0 to disable it.

Yes, it is only about guests so this could be a viable solution too.
I initially wanted to be able to disable all that SEV code but from a
quick glance over it, it is mostly behind an if (sev_active()) check so
I think the module arg should be good enough too.

Thx.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option
  2017-10-02 16:35                     ` Tom Lendacky
@ 2017-10-03 11:29                       ` Borislav Petkov
  0 siblings, 0 replies; 55+ messages in thread
From: Borislav Petkov @ 2017-10-03 11:29 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: Brijesh Singh, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Paolo Bonzini, Radim Krčmář,
	kvm, x86, linux-kernel

On Mon, Oct 02, 2017 at 11:35:47AM -0500, Tom Lendacky wrote:
> Hmmm... strange, I haven't received that email or that part of the thread
> for that matter - including Brijesh's reply.  I'll talk with Brijesh and
> let him run with it.

Yeah, it appears you've been dropped from the thread at some point. But
you should have a separate gmail or so account subscribed to lkml where
to search for all the mails. This helps in situations like that or when
corporate email does it in its pants again.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2017-10-03 11:30 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-27 15:13 [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 01/17] Documentation/x86: Add AMD Secure Encrypted Virtualization (SEV) description Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support Brijesh Singh
2017-09-28  9:02   ` Borislav Petkov
2017-09-28 18:48     ` Brijesh Singh
2017-09-28 19:23       ` Borislav Petkov
2017-09-29 12:28         ` Brijesh Singh
2017-09-29 14:41           ` Borislav Petkov
2017-09-29 15:54             ` Brijesh Singh
2017-09-29 15:56               ` Borislav Petkov
2017-09-29 21:27     ` [Part1 PATCH v5.1 " Brijesh Singh
2017-09-30  8:49       ` Borislav Petkov
2017-09-29 23:06     ` [Part1 PATCH v5 18/18] x86/mm: add 'sme' argument in mem_encrypt= Brijesh Singh
2017-09-30 11:56       ` [PATCH] x86/CPU/AMD, mm: Extend with mem_encrypt=sme option Borislav Petkov
2017-09-30 21:17         ` Brijesh Singh
2017-09-30 21:41           ` Borislav Petkov
2017-10-01 17:00             ` Brijesh Singh
2017-10-01 17:16               ` Borislav Petkov
2017-10-01 19:45                 ` Brijesh Singh
2017-10-01 22:02                   ` Borislav Petkov
2017-10-02 11:32                     ` Brijesh Singh
2017-10-02 12:41                       ` Borislav Petkov
2017-10-02 15:07                         ` Brijesh Singh
2017-10-03 10:50                           ` Paolo Bonzini
2017-10-03 11:20                             ` Borislav Petkov
2017-10-02 13:44                 ` Tom Lendacky
2017-10-02 13:51                   ` Borislav Petkov
2017-10-02 16:35                     ` Tom Lendacky
2017-10-03 11:29                       ` Borislav Petkov
2017-09-27 15:13 ` [Part1 PATCH v5 03/17] x86/mm: Don't attempt to encrypt initrd under SEV Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 04/17] x86/realmode: Don't decrypt trampoline area " Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 05/17] x86/mm: Use encrypted access of boot related data with SEV Brijesh Singh
2017-09-28 11:13   ` Borislav Petkov
2017-09-28 16:20   ` [Part1 PATCH v5.1 " Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 06/17] x86/mm: Include SEV for encryption memory attribute changes Brijesh Singh
2017-09-27 15:53   ` Brijesh Singh
2017-09-27 17:26     ` Borislav Petkov
2017-09-27 19:17   ` [Part1 PATCH v5.1 " Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 07/17] x86/efi: Access EFI data as encrypted when SEV is active Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 08/17] resource: Consolidate resource walking code Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 09/17] resource: Provide resource struct in resource walk callback Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages Brijesh Singh
2017-09-28 16:23   ` Borislav Petkov
2017-09-27 15:13 ` [Part1 PATCH v5 11/17] x86/mm: Add DMA support for SEV memory encryption Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 12/17] x86/boot: Add early boot support when running with SEV active Brijesh Singh
2017-09-28 17:02   ` Borislav Petkov
2017-09-27 15:13 ` [Part1 PATCH v5 13/17] x86/io: Unroll string I/O when SEV is active Brijesh Singh
2017-09-28 17:51   ` Borislav Petkov
2017-09-27 15:13 ` [Part1 PATCH v5 14/17] x86: Add support for changing memory encryption attribute in early boot Brijesh Singh
2017-09-27 15:13 ` [Part1 PATCH v5 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED Brijesh Singh
2017-09-28 20:32   ` Borislav Petkov
2017-09-27 15:13 ` [Part1 PATCH v5 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active Brijesh Singh
2017-09-29  5:51   ` Borislav Petkov
2017-09-27 15:13 ` [Part1 PATCH v5 17/17] X86/KVM: Clear encryption attribute " Brijesh Singh
2017-09-29  6:26 ` [Part1 PATCH v5 00/17] x86: Secure Encrypted Virtualization (AMD) Borislav Petkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).