mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Brijesh Singh <brijesh.singh@amd.com>
To: x86@kernel.org
Cc: bp@alien8.de, Brijesh Singh <brijesh.singh@amd.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, "H. Peter Anvin" <hpa@zytor.com>,
	Borislav Petkov <bp@suse.de>,
	linux-kernel@vger.kernel.org,
	Tom Lendacky <thomas.lendacky@amd.com>
Subject: [Part1 PATCH v6 14/17] x86: Add support for changing memory encryption attribute in early boot
Date: Mon, 16 Oct 2017 10:34:20 -0500	[thread overview]
Message-ID: <20171016153423.2980-15-brijesh.singh@amd.com> (raw)
In-Reply-To: <20171016153423.2980-1-brijesh.singh@amd.com>

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>
---

Changes since v5:

early_set_memory_enc_dec() is enhanced to perform encrypt/decrypt and change
the C bit in one go. The changes shields the caller from having to check
the C bit status before changing it and also shield the OS from converting a
page blindly.

Boris,

I removed your R-b since I was not sure if you are okay with the above changes.
please let me know if you are okay with the changes. thanks

 arch/x86/include/asm/mem_encrypt.h |   8 +++
 arch/x86/mm/mem_encrypt.c          | 131 +++++++++++++++++++++++++++++++++++++
 2 files changed, 139 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 2336c3922227..b671e91e6a1f 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -30,6 +30,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";
@@ -260,6 +262,135 @@ 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, pa, size;
+	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;
+
+	pa = pfn << page_level_shift(level);
+	size = page_level_size(level);
+
+	/*
+	 * We are going to perform in-place encrypt/decrypt and change the
+	 * physical page attribute from C=1 to C=0 or vice versa. Flush the
+	 * caches to ensure that data gets accessed with correct C-bit.
+	 */
+	clflush_cache_range(__va(pa), size);
+
+	/* encrypt/decrypt the contents in-place */
+	if (enc)
+		sme_early_encrypt(pa, size);
+	else
+		sme_early_decrypt(pa, size);
+
+	/* change the page encryption mask */
+	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;
+
+	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

  parent reply	other threads:[~2017-10-16 15:36 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-16 15:34 [Part1 PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 02/17] x86/mm: Add Secure Encrypted Virtualization (SEV) support Brijesh Singh
2017-10-16 16:21   ` Borislav Petkov
2017-10-16 17:46     ` Brijesh Singh
2017-10-16 18:18       ` Borislav Petkov
2017-10-16 19:51   ` [Part1 PATCH v6.1 " Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 03/17] x86/mm: Don't attempt to encrypt initrd under SEV Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 04/17] x86/realmode: Don't decrypt trampoline area " Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 05/17] x86/mm: Use encrypted access of boot related data with SEV Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 06/17] x86/mm: Include SEV for encryption memory attribute changes Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 07/17] x86/efi: Access EFI data as encrypted when SEV is active Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 08/17] resource: Consolidate resource walking code Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 09/17] resource: Provide resource struct in resource walk callback Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 10/17] x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 11/17] x86/mm: Add DMA support for SEV memory encryption Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 12/17] x86/boot: Add early boot support when running with SEV active Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 13/17] x86/io: Unroll string I/O when SEV is active Brijesh Singh
2017-10-16 15:34 ` Brijesh Singh [this message]
2017-10-16 18:20   ` [Part1 PATCH v6 14/17] x86: Add support for changing memory encryption attribute in early boot Borislav Petkov
2017-10-16 19:56   ` [Part1 PATCH v6.1 " Brijesh Singh
2017-10-16 21:25     ` Borislav Petkov
2017-10-16 15:34 ` [Part1 PATCH v6 15/17] percpu: Introduce DEFINE_PER_CPU_DECRYPTED Brijesh Singh
2017-10-16 15:34 ` [Part1 PATCH v6 16/17] X86/KVM: Decrypt shared per-cpu variables when SEV is active Brijesh Singh
2017-10-16 22:24   ` Borislav Petkov
2017-10-17  1:43     ` Brijesh Singh
2017-10-17  8:20       ` Borislav Petkov
2017-10-17 11:54         ` Brijesh Singh
2017-10-17 13:35           ` Borislav Petkov
2017-10-17 15:42             ` Brijesh Singh
2017-10-17 16:23               ` Borislav Petkov
2017-10-19 13:44   ` [Part1 PATCH v6.1 " Brijesh Singh
2017-10-19 15:40     ` Borislav Petkov
2017-10-16 15:34 ` [Part1 PATCH v6 17/17] X86/KVM: Clear encryption attribute " Brijesh Singh
2017-10-19 13:47   ` [Part1 PATCH v6.1 " Brijesh Singh
2017-10-16 15:42 ` [Part1 PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-10-20  9:24 ` Borislav Petkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171016153423.2980-15-brijesh.singh@amd.com \
    --to=brijesh.singh@amd.com \
    --cc=bp@alien8.de \
    --cc=bp@suse.de \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®