Linux cryptographic layer development
 help / color / mirror / Atom feed
* [RFC PATCH v1 04/28] x86: Secure Encrypted Virtualization (SEV) support
From: Brijesh Singh @ 2016-08-22 23:24 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

Provide support for Secure Encyrpted Virtualization (SEV). This initial
support defines the SEV active flag in order for the kernel to determine
if it is running with SEV active or not.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |    3 +++
 arch/x86/kernel/mem_encrypt.S      |    8 ++++++++
 arch/x86/kernel/x8664_ksyms_64.c   |    1 +
 3 files changed, 12 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index e395729..9c592d1 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -20,6 +20,7 @@
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern unsigned long sme_me_mask;
+extern unsigned int sev_active;
 
 u8 sme_get_me_loss(void);
 
@@ -50,6 +51,8 @@ void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
 
 #define sme_me_mask		0UL
 
+#define sev_active		0
+
 static inline u8 sme_get_me_loss(void)
 {
 	return 0;
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index bf9f6a9..6a8cd18 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -96,6 +96,10 @@ ENDPROC(sme_enable)
 
 ENTRY(sme_encrypt_kernel)
 #ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* If SEV is active then the kernel is already encrypted */
+	cmpl	$0, sev_active(%rip)
+	jnz	.Lencrypt_exit
+
 	/* If SME is not active then no need to encrypt the kernel */
 	cmpq	$0, sme_me_mask(%rip)
 	jz	.Lencrypt_exit
@@ -334,6 +338,10 @@ sme_me_loss:
 	.byte	0x00
 	.align	8
 
+ENTRY(sev_active)
+	.word	0x00000000
+	.align	8
+
 mem_encrypt_enable_option:
 	.asciz "mem_encrypt=on"
 	.align	8
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 651c4c8..14bfc0b 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -88,4 +88,5 @@ EXPORT_SYMBOL(___preempt_schedule_notrace);
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 EXPORT_SYMBOL_GPL(sme_me_mask);
 EXPORT_SYMBOL_GPL(sme_get_me_loss);
+EXPORT_SYMBOL_GPL(sev_active);
 #endif

^ permalink raw reply related

* [RFC PATCH v1 12/28] x86: DMA support for SEV memory encryption
From: Brijesh Singh @ 2016-08-22 23:26 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

DMA access to memory mapped as encrypted while SEV is active can not be
encrypted during device write or decrypted during device read. In order
for DMA to properly work when SEV is active, the swiotlb bounce buffers
must be used.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/mem_encrypt.c |   48 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 1154353..ce6e3ea 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -173,8 +173,52 @@ 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(pgprot_val(protection_map[i]) | sme_me_mask);
+
+	if (sev_active)
+		swiotlb_force = 1;
 }
 
+static void *sme_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		       gfp_t gfp, unsigned long attrs)
+{
+	void *vaddr;
+
+	vaddr = x86_swiotlb_alloc_coherent(dev, size, dma_handle, gfp, attrs);
+	if (!vaddr)
+		return NULL;
+
+	/* Clear the SME encryption bit for DMA use */
+	sme_set_mem_dec(vaddr, size);
+
+	/* Remove the encryption bit from the DMA address */
+	*dma_handle &= ~sme_me_mask;
+
+	return vaddr;
+}
+
+static void sme_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 as encrypted */
+	sme_set_mem_enc(vaddr, size);
+
+	x86_swiotlb_free_coherent(dev, size, vaddr, dma_handle, attrs);
+}
+
+static struct dma_map_ops sme_dma_ops = {
+	.alloc                  = sme_alloc,
+	.free                   = sme_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)
 {
@@ -184,6 +228,10 @@ void __init mem_encrypt_init(void)
 	/* Make SWIOTLB use an unencrypted DMA area */
 	swiotlb_clear_encryption();
 
+	/* Use SEV DMA operations if SEV is active */
+	if (sev_active)
+		dma_ops = &sme_dma_ops;
+
 	pr_info("memory encryption active\n");
 }
 

^ permalink raw reply related

* [RFC PATCH v1 02/28] kvm: svm: Add kvm_fast_pio_in support
From: Brijesh Singh @ 2016-08-22 23:23 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

Update the I/O interception support to add the kvm_fast_pio_in function
to speed up the in instruction similar to the out instruction.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/kvm_host.h |    1 +
 arch/x86/kvm/svm.c              |    5 +++--
 arch/x86/kvm/x86.c              |   43 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 3f05d36..c38f878 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1133,6 +1133,7 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr);
 struct x86_emulate_ctxt;
 
 int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port);
+int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, unsigned short port);
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
 int kvm_emulate_halt(struct kvm_vcpu *vcpu);
 int kvm_vcpu_halt(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index d8b9c8c..fd5a9a8 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2131,7 +2131,7 @@ static int io_interception(struct vcpu_svm *svm)
 	++svm->vcpu.stat.io_exits;
 	string = (io_info & SVM_IOIO_STR_MASK) != 0;
 	in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
-	if (string || in)
+	if (string)
 		return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 
 	port = io_info >> 16;
@@ -2139,7 +2139,8 @@ static int io_interception(struct vcpu_svm *svm)
 	svm->next_rip = svm->vmcb->control.exit_info_2;
 	skip_emulated_instruction(&svm->vcpu);
 
-	return kvm_fast_pio_out(vcpu, size, port);
+	return in ? kvm_fast_pio_in(vcpu, size, port)
+		  : kvm_fast_pio_out(vcpu, size, port);
 }
 
 static int nmi_interception(struct vcpu_svm *svm)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d432894..78295b0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5579,6 +5579,49 @@ int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port)
 }
 EXPORT_SYMBOL_GPL(kvm_fast_pio_out);
 
+static int complete_fast_pio_in(struct kvm_vcpu *vcpu)
+{
+	unsigned long val;
+
+	/* We should only ever be called with arch.pio.count equal to 1 */
+	BUG_ON(vcpu->arch.pio.count != 1);
+
+	/* For size less than 4 we merge, else we zero extend */
+	val = (vcpu->arch.pio.size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX)
+					: 0;
+
+	/*
+	 * Since vcpu->arch.pio.count == 1 let emulator_pio_in_emulated perform
+	 * the copy and tracing
+	 */
+	emulator_pio_in_emulated(&vcpu->arch.emulate_ctxt, vcpu->arch.pio.size,
+				 vcpu->arch.pio.port, &val, 1);
+	kvm_register_write(vcpu, VCPU_REGS_RAX, val);
+
+	return 1;
+}
+
+int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, unsigned short port)
+{
+	unsigned long val;
+	int ret;
+
+	/* For size less than 4 we merge, else we zero extend */
+	val = (size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX) : 0;
+
+	ret = emulator_pio_in_emulated(&vcpu->arch.emulate_ctxt, size, port,
+				       &val, 1);
+	if (ret) {
+		kvm_register_write(vcpu, VCPU_REGS_RAX, val);
+		return ret;
+	}
+
+	vcpu->arch.complete_userspace_io = complete_fast_pio_in;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_fast_pio_in);
+
 static int kvmclock_cpu_down_prep(unsigned int cpu)
 {
 	__this_cpu_write(cpu_tsc_khz, 0);

^ permalink raw reply related

* [RFC PATCH v1 00/28] x86: Secure Encrypted Virtualization (AMD)
From: Brijesh Singh @ 2016-08-22 23:23 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab

This RFC series provides support for AMD's new Secure Encrypted 
Virtualization (SEV) feature. This RFC is build upon Secure Memory 
Encryption (SME) RFC.

SEV is an extension to the AMD-V architecture which supports running 
multiple VMs under the control of a hypervisor. When enabled, SEV 
hardware tags all code and data with its VM ASID which indicates which 
VM the data originated from or is intended for. This tag is kept with 
the data at all times when inside the SOC, and prevents that data from 
being used by anyone other than the owner. While the tag protects VM 
data inside the SOC, AES with 128 bit encryption protects data outside 
the SOC. When data leaves or enters the SOC, it is encrypted/decrypted 
respectively by hardware with a key based on the associated tag.

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.  Certain types of memory (namely instruction pages and
guest page tables) are always treated as private memory by the hardware.
For data memory, SEV guest VMs can choose which pages they would like to
be private. The choice is done using the standard CPU page tables using
the C-bit, and is fully controlled by the guest. Due to security reasons
all the DMA operations inside the  guest must be performed on shared pages
(C-bit clear).  Note that since C-bit is only controllable 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 C-bit to a 1.

SEV is designed to protect guest VMs from a benign but vulnerable
(i.e. not fully malicious) hypervisor. In particular, it reduces the attack
surface of guest VMs and can prevent certain types of VM-escape bugs
(e.g. hypervisor read-anywhere) from being used to steal guest data.

The RFC series also includes a crypto driver (psp.ko) which communicates
with SEV firmware that runs within the AMD secure processor provides a
secure key management interfaces. The hypervisor uses this interface to 
enable SEV for secure guest and perform common hypervisor activities
such as launching, running, snapshotting , migrating and debugging a 
guest. A new ioctl (KVM_SEV_ISSUE_CMD) is introduced which will enable
Qemu to send commands to the SEV firmware during guest life cycle.

The RFC series also includes patches required in guest OS to enable SEV 
feature. A guest OS can check SEV support by calling KVM_FEATURE cpuid 
instruction.

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_Spec.pdf

---

TODO:
- send qemu/seabios RFC's on respective mailing list
- integrate the psp driver with CCP driver (they share the PCI id's)
- add SEV guest migration command support
- add SEV snapshotting command support
- determine how to do ioremap of physical memory with mem encryption enabled
  (e.g acpi tables)
- determine how to share the guest memory with hypervisor for to support
  pvclock driver

Brijesh Singh (11):
      crypto: add AMD Platform Security Processor driver
      KVM: SVM: prepare to reserve asid for SEV guest
      KVM: SVM: prepare for SEV guest management API support
      KVM: introduce KVM_SEV_ISSUE_CMD ioctl
      KVM: SVM: add SEV launch start command
      KVM: SVM: add SEV launch update command
      KVM: SVM: add SEV_LAUNCH_FINISH command
      KVM: SVM: add KVM_SEV_GUEST_STATUS command
      KVM: SVM: add KVM_SEV_DEBUG_DECRYPT command
      KVM: SVM: add KVM_SEV_DEBUG_ENCRYPT command
      KVM: SVM: add command to query SEV API version

Tom Lendacky (17):
      kvm: svm: Add support for additional SVM NPF error codes
      kvm: svm: Add kvm_fast_pio_in support
      kvm: svm: Use the hardware provided GPA instead of page walk
      x86: Secure Encrypted Virtualization (SEV) support
      KVM: SVM: prepare for new bit definition in nested_ctl
      KVM: SVM: Add SEV feature definitions to KVM
      x86: Do not encrypt memory areas if SEV is enabled
      Access BOOT related data encrypted with SEV active
      x86/efi: Access EFI data as encrypted when SEV is active
      x86: Change early_ioremap to early_memremap for BOOT data
      x86: Don't decrypt trampoline area if SEV is active
      x86: DMA support for SEV memory encryption
      iommu/amd: AMD IOMMU support for SEV
      x86: Don't set the SME MSR bit when SEV is active
      x86: Unroll string I/O when SEV is active
      x86: Add support to determine if running with SEV enabled
      KVM: SVM: Enable SEV by setting the SEV_ENABLE cpu feature


 arch/x86/boot/compressed/Makefile      |    2 
 arch/x86/boot/compressed/head_64.S     |   19 +
 arch/x86/boot/compressed/mem_encrypt.S |  123 ++++
 arch/x86/include/asm/io.h              |   26 +
 arch/x86/include/asm/kvm_emulate.h     |    3 
 arch/x86/include/asm/kvm_host.h        |   27 +
 arch/x86/include/asm/mem_encrypt.h     |    3 
 arch/x86/include/asm/svm.h             |    3 
 arch/x86/include/uapi/asm/hyperv.h     |    4 
 arch/x86/include/uapi/asm/kvm_para.h   |    4 
 arch/x86/kernel/acpi/boot.c            |    4 
 arch/x86/kernel/head64.c               |    4 
 arch/x86/kernel/mem_encrypt.S          |   44 ++
 arch/x86/kernel/mpparse.c              |   10 
 arch/x86/kernel/setup.c                |    7 
 arch/x86/kernel/x8664_ksyms_64.c       |    1 
 arch/x86/kvm/cpuid.c                   |    4 
 arch/x86/kvm/mmu.c                     |   20 +
 arch/x86/kvm/svm.c                     |  906 ++++++++++++++++++++++++++++++++
 arch/x86/kvm/x86.c                     |   73 +++
 arch/x86/mm/ioremap.c                  |    7 
 arch/x86/mm/mem_encrypt.c              |   50 ++
 arch/x86/platform/efi/efi_64.c         |   14 
 arch/x86/realmode/init.c               |   11 
 drivers/crypto/Kconfig                 |   11 
 drivers/crypto/Makefile                |    1 
 drivers/crypto/psp/Kconfig             |    8 
 drivers/crypto/psp/Makefile            |    3 
 drivers/crypto/psp/psp-dev.c           |  220 ++++++++
 drivers/crypto/psp/psp-dev.h           |   95 +++
 drivers/crypto/psp/psp-ops.c           |  454 ++++++++++++++++
 drivers/crypto/psp/psp-pci.c           |  376 +++++++++++++
 drivers/sfi/sfi_core.c                 |    6 
 include/linux/ccp-psp.h                |  833 +++++++++++++++++++++++++++++
 include/uapi/linux/Kbuild              |    1 
 include/uapi/linux/ccp-psp.h           |  182 ++++++
 include/uapi/linux/kvm.h               |  125 ++++
 37 files changed, 3643 insertions(+), 41 deletions(-)
 create mode 100644 arch/x86/boot/compressed/mem_encrypt.S
 create mode 100644 drivers/crypto/psp/Kconfig
 create mode 100644 drivers/crypto/psp/Makefile
 create mode 100644 drivers/crypto/psp/psp-dev.c
 create mode 100644 drivers/crypto/psp/psp-dev.h
 create mode 100644 drivers/crypto/psp/psp-ops.c
 create mode 100644 drivers/crypto/psp/psp-pci.c
 create mode 100644 include/linux/ccp-psp.h
 create mode 100644 include/uapi/linux/ccp-psp.h

-- 

Brijesh Singh

^ permalink raw reply

* [RFC PATCH v1 13/28] iommu/amd: AMD IOMMU support for SEV
From: Brijesh Singh @ 2016-08-22 23:26 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

DMA must be performed to memory that is not mapped encrypted when running
with SEV active. So if SEV is active, do not return the encryption mask
to the IOMMU.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/mem_encrypt.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index ce6e3ea..d6e9f96 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -237,7 +237,7 @@ void __init mem_encrypt_init(void)
 
 unsigned long amd_iommu_get_me_mask(void)
 {
-	return sme_me_mask;
+	return sev_active ? 0 : sme_me_mask;
 }
 
 unsigned long swiotlb_get_me_mask(void)

^ permalink raw reply related

* [RFC PATCH v1 08/28] Access BOOT related data encrypted with SEV active
From: Brijesh Singh @ 2016-08-22 23:25 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

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

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/ioremap.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index e3bdc5a..2ea6deb 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -429,10 +429,11 @@ pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
 					     pgprot_t prot)
 {
 	/*
-	 * If memory encryption is enabled and BOOT_DATA is being mapped
-	 * then remove the encryption bit.
+	 * If memory encryption is enabled, we are not running with
+	 * SEV active and BOOT_DATA is being mapped then remove the
+	 * encryption bit
 	 */
-	if (_PAGE_ENC && (owner == BOOT_DATA))
+	if (_PAGE_ENC && !sev_active && (owner == BOOT_DATA))
 		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
 
 	return prot;

^ permalink raw reply related

* [RFC PATCH v1 06/28] KVM: SVM: Add SEV feature definitions to KVM
From: Brijesh Singh @ 2016-08-22 23:24 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

Define a new KVM cpu feature for Secure Encrypted Virtualization (SEV).
The kernel will check for the presence of this feature to determine if
it is running with SEV active.

Define the SEV enable bit for the VMCB control structure. The hypervisor
will use this bit to enable SEV in the guest.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/svm.h           |    1 +
 arch/x86/include/uapi/asm/kvm_para.h |    1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 2aca535..fba2a7b 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -137,6 +137,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
 #define SVM_VM_CR_SVM_DIS_MASK  0x0010ULL
 
 #define SVM_NESTED_CTL_NP_ENABLE	BIT(0)
+#define SVM_NESTED_CTL_SEV_ENABLE	BIT(1)
 
 struct __attribute__ ((__packed__)) vmcb_seg {
 	u16 selector;
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
index 94dc8ca..67dd610f 100644
--- a/arch/x86/include/uapi/asm/kvm_para.h
+++ b/arch/x86/include/uapi/asm/kvm_para.h
@@ -24,6 +24,7 @@
 #define KVM_FEATURE_STEAL_TIME		5
 #define KVM_FEATURE_PV_EOI		6
 #define KVM_FEATURE_PV_UNHALT		7
+#define KVM_FEATURE_SEV			8
 
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.

^ permalink raw reply related

* [RFC PATCH v1 14/28] x86: Don't set the SME MSR bit when SEV is active
From: Brijesh Singh @ 2016-08-22 23:26 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

When SEV is active the virtual machine cannot set the MSR for SME, so
don't set the trampoline flag for SME.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/realmode/init.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f3207e5..391d8ba 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -102,7 +102,7 @@ static void __init setup_real_mode(void)
 	*trampoline_cr4_features = mmu_cr4_features;
 
 	trampoline_header->flags = 0;
-	if (sme_me_mask)
+	if (sme_me_mask && !sev_active)
 		trampoline_header->flags |= TH_FLAGS_SME_ENABLE;
 
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);

^ permalink raw reply related

* [RFC PATCH v1 11/28] x86: Don't decrypt trampoline area if SEV is active
From: Brijesh Singh @ 2016-08-22 23:25 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

When Secure Encrypted Virtualization is active instruction fetches are
always interpreted as being from encrypted memory so the trampoline area
must remain encrypted when SEV is active.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/realmode/init.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index c3edb49..f3207e5 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -138,10 +138,13 @@ static void __init set_real_mode_permissions(void)
 	/*
 	 * If memory encryption is active, the trampoline area will need to
 	 * be in non-encrypted memory in order to bring up other processors
-	 * successfully.
+	 * successfully. This only applies to SME, SEV requires the trampoline
+	 * to be encrypted.
 	 */
-	sme_early_mem_dec(__pa(base), size);
-	sme_set_mem_dec(base, size);
+	if (!sev_active) {
+		sme_early_mem_dec(__pa(base), size);
+		sme_set_mem_dec(base, size);
+	}
 
 	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
 	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);

^ permalink raw reply related

* [RFC PATCH v1 10/28] x86: Change early_ioremap to early_memremap for BOOT data
From: Brijesh Singh @ 2016-08-22 23:25 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/acpi/boot.c |    4 ++--
 arch/x86/kernel/mpparse.c   |   10 +++++-----
 drivers/sfi/sfi_core.c      |    6 +++---
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 1ad5fe2..4622ea2 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -120,7 +120,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 	if (!phys || !size)
 		return NULL;
 
-	return early_ioremap(phys, size);
+	return early_memremap(phys, size, BOOT_DATA);
 }
 
 void __init __acpi_unmap_table(char *map, unsigned long size)
@@ -128,7 +128,7 @@ void __init __acpi_unmap_table(char *map, unsigned long size)
 	if (!map || !size)
 		return;
 
-	early_iounmap(map, size);
+	early_memunmap(map, size);
 }
 
 #ifdef CONFIG_X86_LOCAL_APIC
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 0f8d204..04def9f 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -436,9 +436,9 @@ static unsigned long __init get_mpc_size(unsigned long physptr)
 	struct mpc_table *mpc;
 	unsigned long size;
 
-	mpc = early_ioremap(physptr, PAGE_SIZE);
+	mpc = early_memremap(physptr, PAGE_SIZE, BOOT_DATA);
 	size = mpc->length;
-	early_iounmap(mpc, PAGE_SIZE);
+	early_memunmap(mpc, PAGE_SIZE);
 	apic_printk(APIC_VERBOSE, "  mpc: %lx-%lx\n", physptr, physptr + size);
 
 	return size;
@@ -450,7 +450,7 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
 	unsigned long size;
 
 	size = get_mpc_size(mpf->physptr);
-	mpc = early_ioremap(mpf->physptr, size);
+	mpc = early_memremap(mpf->physptr, size, BOOT_DATA);
 	/*
 	 * Read the physical hardware table.  Anything here will
 	 * override the defaults.
@@ -461,10 +461,10 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
 #endif
 		pr_err("BIOS bug, MP table errors detected!...\n");
 		pr_cont("... disabling SMP support. (tell your hw vendor)\n");
-		early_iounmap(mpc, size);
+		early_memunmap(mpc, size);
 		return -1;
 	}
-	early_iounmap(mpc, size);
+	early_memunmap(mpc, size);
 
 	if (early)
 		return -1;
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
index 296db7a..3078d35 100644
--- a/drivers/sfi/sfi_core.c
+++ b/drivers/sfi/sfi_core.c
@@ -92,7 +92,7 @@ static struct sfi_table_simple *syst_va __read_mostly;
 static u32 sfi_use_ioremap __read_mostly;
 
 /*
- * sfi_un/map_memory calls early_ioremap/iounmap which is a __init function
+ * sfi_un/map_memory calls early_memremap/memunmap which is a __init function
  * and introduces section mismatch. So use __ref to make it calm.
  */
 static void __iomem * __ref sfi_map_memory(u64 phys, u32 size)
@@ -103,7 +103,7 @@ static void __iomem * __ref sfi_map_memory(u64 phys, u32 size)
 	if (sfi_use_ioremap)
 		return ioremap_cache(phys, size);
 	else
-		return early_ioremap(phys, size);
+		return early_memremap(phys, size, BOOT_DATA);
 }
 
 static void __ref sfi_unmap_memory(void __iomem *virt, u32 size)
@@ -114,7 +114,7 @@ static void __ref sfi_unmap_memory(void __iomem *virt, u32 size)
 	if (sfi_use_ioremap)
 		iounmap(virt);
 	else
-		early_iounmap(virt, size);
+		early_memunmap(virt, size);
 }
 
 static void sfi_print_table_header(unsigned long long pa,

^ permalink raw reply related

* [RFC PATCH v1 16/28] x86: Add support to determine if running with SEV enabled
From: Brijesh Singh @ 2016-08-22 23:26 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

Early in the boot process, add a check to determine if the kernel is
running with Secure Encrypted Virtualization (SEV) enabled. If active,
the kernel will perform steps necessary to insure the proper kernel
initialization process is performed.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/boot/compressed/Makefile      |    2 +
 arch/x86/boot/compressed/head_64.S     |   19 +++++
 arch/x86/boot/compressed/mem_encrypt.S |  123 ++++++++++++++++++++++++++++++++
 arch/x86/include/uapi/asm/hyperv.h     |    4 +
 arch/x86/include/uapi/asm/kvm_para.h   |    3 +
 arch/x86/kernel/mem_encrypt.S          |   36 +++++++++
 6 files changed, 187 insertions(+)
 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 536ccfc..4888df9 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -73,6 +73,8 @@ vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
 	$(obj)/string.o $(obj)/cmdline.o $(obj)/error.o \
 	$(obj)/piggy.o $(obj)/cpuflags.o
 
+vmlinux-objs-$(CONFIG_X86_64) += $(obj)/mem_encrypt.o
+
 vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o
 vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o
 ifdef CONFIG_X86_64
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 0d80a7a..acb907a 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -131,6 +131,19 @@ ENTRY(startup_32)
  /*
   * Build early 4G boot pagetable
   */
+	/*
+	 * If SEV is active 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	sev_active
+	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
@@ -141,12 +154,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
@@ -157,6 +172,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
@@ -344,6 +360,9 @@ preferred_addr:
 	subl	$_end, %ebx
 	addq	%rbp, %rbx
 
+	/* Check for SEV and adjust page tables as necessary */
+	call	sev_adjust
+
 	/* Set up the stack */
 	leaq	boot_stack_end(%rbx), %rsp
 
diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S
new file mode 100644
index 0000000..56e19f6
--- /dev/null
+++ b/arch/x86/boot/compressed/mem_encrypt.S
@@ -0,0 +1,123 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 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>
+#include <uapi/asm/kvm_para.h>
+
+	.text
+	.code32
+ENTRY(sev_active)
+	xor	%eax, %eax
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	push	%ebx
+	push	%ecx
+	push	%edx
+
+	/* Check if running under a hypervisor */
+	movl	$0x40000000, %eax
+	cpuid
+	cmpl	$0x40000001, %eax
+	jb	.Lno_sev
+
+	movl	$0x40000001, %eax
+	cpuid
+	bt	$KVM_FEATURE_SEV, %eax
+	jnc	.Lno_sev
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lno_sev
+
+	/*
+	 * Get memory encryption information:
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 */
+	movl	%ebx, %eax
+	andl	$0x3f, %eax
+	jmp	.Lsev_exit
+
+.Lno_sev:
+	xor	%eax, %eax
+
+.Lsev_exit:
+	pop	%edx
+	pop	%ecx
+	pop	%ebx
+
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+	ret
+ENDPROC(sev_active)
+
+	.code64
+ENTRY(sev_adjust)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	push	%rax
+	push	%rbx
+	push	%rcx
+	push	%rdx
+
+	/* Check if running under a hypervisor */
+	movl	$0x40000000, %eax
+	cpuid
+	cmpl	$0x40000001, %eax
+	jb	.Lno_adjust
+
+	movl	$0x40000001, %eax
+	cpuid
+	bt	$KVM_FEATURE_SEV, %eax
+	jnc	.Lno_adjust
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lno_adjust
+
+	/*
+	 * Get memory encryption information:
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 */
+	movl	%ebx, %ecx
+	andl	$0x3f, %ecx
+	jz	.Lno_adjust
+
+	/*
+	 * Adjust/verify the page table entries to include the encryption
+	 * mask for the area where the compressed kernel is copied and
+	 * the area the kernel is decompressed into
+	 */
+
+.Lno_adjust:
+	pop	%rdx
+	pop	%rcx
+	pop	%rbx
+	pop	%rax
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+	ret
+ENDPROC(sev_adjust)
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index 9b1a918..8278161 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -3,6 +3,8 @@
 
 #include <linux/types.h>
 
+#ifndef __ASSEMBLY__
+
 /*
  * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
  * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
@@ -363,4 +365,6 @@ struct hv_timer_message_payload {
 #define HV_STIMER_AUTOENABLE		(1ULL << 3)
 #define HV_STIMER_SINT(config)		(__u8)(((config) >> 16) & 0x0F)
 
+#endif	/* __ASSEMBLY__ */
+
 #endif
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
index 67dd610f..5788561 100644
--- a/arch/x86/include/uapi/asm/kvm_para.h
+++ b/arch/x86/include/uapi/asm/kvm_para.h
@@ -26,6 +26,8 @@
 #define KVM_FEATURE_PV_UNHALT		7
 #define KVM_FEATURE_SEV			8
 
+#ifndef __ASSEMBLY__
+
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.
  */
@@ -98,5 +100,6 @@ struct kvm_vcpu_pv_apf_data {
 #define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
 #define KVM_PV_EOI_DISABLED 0x0
 
+#endif	/* __ASSEMBLY__ */
 
 #endif /* _UAPI_ASM_X86_KVM_PARA_H */
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index 6a8cd18..78fc608 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -17,11 +17,47 @@
 #include <asm/page.h>
 #include <asm/msr.h>
 #include <asm/asm-offsets.h>
+#include <uapi/asm/kvm_para.h>
 
 	.text
 	.code64
 ENTRY(sme_enable)
 #ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* Check if running under a hypervisor */
+	movl	$0x40000000, %eax
+	cpuid
+	cmpl	$0x40000001, %eax
+	jb	.Lno_hyp
+
+	movl	$0x40000001, %eax
+	cpuid
+	bt	$KVM_FEATURE_SEV, %eax
+	jnc	.Lno_mem_encrypt
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lno_mem_encrypt
+
+	/*
+	 * Get memory encryption information:
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 */
+	movl	%ebx, %ecx
+	andl	$0x3f, %ecx
+	jz	.Lno_mem_encrypt
+	bts	%ecx, sme_me_mask(%rip)
+
+	/* Indicate that SEV is active */
+	movl	$1, sev_active(%rip)
+	jmp	.Lmem_encrypt_exit
+
+.Lno_hyp:
 	/* Check for AMD processor */
 	xorl	%eax, %eax
 	cpuid

^ permalink raw reply related

* [RFC PATCH v1 15/28] x86: Unroll string I/O when SEV is active
From: Brijesh Singh @ 2016-08-22 23:26 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/io.h |   26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index de25aad..130b3e2 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -303,14 +303,32 @@ 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));		\
+	if (sev_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));	\
+	}								\
 }									\
 									\
 static inline void ins##bwl(int port, void *addr, unsigned long count)	\
 {									\
-	asm volatile("rep; ins" #bwl					\
-		     : "+D"(addr), "+c"(count) : "d"(port));		\
+	if (sev_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));	\
+	}								\
 }
 
 BUILDIO(b, b, char)

^ permalink raw reply related

* [RFC PATCH v1 20/28] KVM: SVM: prepare for SEV guest management API support
From: Brijesh Singh @ 2016-08-22 23:28 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

The patch adds initial support required for Secure Encrypted
Virtualization (SEV) guest management API's.

ASID management:
 - Reserve asid range for SEV guest, SEV asid range is obtained
   through CPUID Fn8000_001f[ECX]. A non-SEV guest can use any
   asid outside the SEV asid range.
 - SEV guest must have asid value within asid range obtained
   through CPUID.
 - SEV guest must have the same asid for all vcpu's. A TLB flush
   is required if different vcpu for the same ASID is to be run
   on the same host CPU.

- save SEV private structure in kvm_arch.

- If SEV is available then initialize PSP firmware during hardware probe

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/include/asm/kvm_host.h |    9 ++
 arch/x86/kvm/svm.c              |  213 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index b1dd673..9b885fc 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -715,6 +715,12 @@ struct kvm_hv {
 	u64 hv_crash_ctl;
 };
 
+struct kvm_sev_info {
+	unsigned int asid;	/* asid for this guest */
+	unsigned int handle;	/* firmware handle */
+	unsigned int ref_count; /* number of active vcpus */
+};
+
 struct kvm_arch {
 	unsigned int n_used_mmu_pages;
 	unsigned int n_requested_mmu_pages;
@@ -799,6 +805,9 @@ struct kvm_arch {
 
 	bool x2apic_format;
 	bool x2apic_broadcast_quirk_disabled;
+
+	/* struct for SEV guest */
+	struct kvm_sev_info sev_info;
 };
 
 struct kvm_vm_stat {
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index f010b23..dcee635 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -34,6 +34,7 @@
 #include <linux/sched.h>
 #include <linux/trace_events.h>
 #include <linux/slab.h>
+#include <linux/ccp-psp.h>
 
 #include <asm/apic.h>
 #include <asm/perf_event.h>
@@ -186,6 +187,9 @@ struct vcpu_svm {
 	struct page *avic_backing_page;
 	u64 *avic_physical_id_cache;
 	bool avic_is_running;
+
+	/* which host cpu was used for running this vcpu */
+	bool last_cpuid;
 };
 
 #define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK	(0xFF)
@@ -243,6 +247,25 @@ static int avic;
 module_param(avic, int, S_IRUGO);
 #endif
 
+/* Secure Encrypted Virtualization */
+static bool sev_enabled;
+static unsigned long max_sev_asid;
+static unsigned long *sev_asid_bitmap;
+
+#define kvm_sev_guest()		(kvm->arch.sev_info.handle)
+#define kvm_sev_handle()	(kvm->arch.sev_info.handle)
+#define kvm_sev_ref()		(kvm->arch.sev_info.ref_count++)
+#define kvm_sev_unref()		(kvm->arch.sev_info.ref_count--)
+#define svm_sev_handle()	(svm->vcpu.kvm->arch.sev_info.handle)
+#define svm_sev_asid()		(svm->vcpu.kvm->arch.sev_info.asid)
+#define svm_sev_ref()		(svm->vcpu.kvm->arch.sev_info.ref_count++)
+#define svm_sev_unref()		(svm->vcpu.kvm->arch.sev_info.ref_count--)
+#define svm_sev_guest()		(svm->vcpu.kvm->arch.sev_info.handle)
+#define svm_sev_ref_count()	(svm->vcpu.kvm->arch.sev_info.ref_count)
+
+static int sev_asid_new(void);
+static void sev_asid_free(int asid);
+
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
 static void svm_complete_interrupts(struct vcpu_svm *svm);
@@ -474,6 +497,8 @@ struct svm_cpu_data {
 	struct kvm_ldttss_desc *tss_desc;
 
 	struct page *save_area;
+
+	void **sev_vmcb;  /* index = sev_asid, value = vmcb pointer */
 };
 
 static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
@@ -727,7 +752,10 @@ static int svm_hardware_enable(void)
 	sd->asid_generation = 1;
 	sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
 	sd->next_asid = sd->max_asid + 1;
-	sd->min_asid = 1;
+	sd->min_asid = max_sev_asid + 1;
+
+	if (sev_enabled)
+		memset(sd->sev_vmcb, 0, (max_sev_asid + 1) * sizeof(void *));
 
 	native_store_gdt(&gdt_descr);
 	gdt = (struct desc_struct *)gdt_descr.address;
@@ -788,6 +816,7 @@ static void svm_cpu_uninit(int cpu)
 
 	per_cpu(svm_data, raw_smp_processor_id()) = NULL;
 	__free_page(sd->save_area);
+	kfree(sd->sev_vmcb);
 	kfree(sd);
 }
 
@@ -805,6 +834,14 @@ static int svm_cpu_init(int cpu)
 	if (!sd->save_area)
 		goto err_1;
 
+	if (sev_enabled) {
+		sd->sev_vmcb = kmalloc((max_sev_asid + 1) * sizeof(void *),
+					GFP_KERNEL);
+		r = -ENOMEM;
+		if (!sd->sev_vmcb)
+			goto err_1;
+	}
+
 	per_cpu(svm_data, cpu) = sd;
 
 	return 0;
@@ -931,6 +968,74 @@ static void svm_disable_lbrv(struct vcpu_svm *svm)
 	set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
 }
 
+static __init void sev_hardware_setup(void)
+{
+	int ret, psp_ret;
+	struct psp_data_init *init;
+	struct psp_data_status *status;
+
+	/*
+	 * Check SEV Feature Support: Fn8001_001F[EAX]
+	 * 	Bit 1: Secure Memory Virtualization supported
+	 */
+	if (!(cpuid_eax(0x8000001F) & 0x2))
+		return;
+
+	/*
+	 * Get maximum number of encrypted guest supported: Fn8001_001F[ECX]
+	 * 	Bit 31:0: Number of supported guest
+	 */
+	max_sev_asid = cpuid_ecx(0x8000001F);
+	if (!max_sev_asid)
+		return;
+
+	init = kzalloc(sizeof(*init), GFP_KERNEL);
+	if (!init)
+		return;
+
+	status = kzalloc(sizeof(*status), GFP_KERNEL);
+	if (!status)
+		goto err_1;
+
+	/* Initialize PSP firmware */
+	init->hdr.buffer_len = sizeof(*init);
+	init->flags = 0;
+	ret = psp_platform_init(init, &psp_ret);
+	if (ret) {
+		printk(KERN_ERR "SEV: PSP_INIT ret=%d (%#x)\n", ret, psp_ret);
+		goto err_2;
+	}
+
+	/* Initialize SEV ASID bitmap */
+	sev_asid_bitmap = kmalloc(max(sizeof(unsigned long),
+				      max_sev_asid/8 + 1), GFP_KERNEL);
+	if (IS_ERR(sev_asid_bitmap)) {
+		psp_platform_shutdown(&psp_ret);
+		goto err_2;
+	}
+	bitmap_zero(sev_asid_bitmap, max_sev_asid);
+	set_bit(0, sev_asid_bitmap);  /* mark ASID 0 as used */
+
+	sev_enabled = 1;
+	printk(KERN_INFO "kvm: SEV enabled\n");
+
+	/* Query the platform status and print API version */
+	status->hdr.buffer_len = sizeof(*status);
+	ret = psp_platform_status(status, &psp_ret);
+	if (ret) {
+		printk(KERN_ERR "SEV: PLATFORM_STATUS ret=%#x\n", psp_ret);
+		goto err_2;
+	}
+
+	printk(KERN_INFO "SEV API: %d.%d\n",
+			status->api_major, status->api_minor);
+err_2:
+	kfree(status);
+err_1:
+	kfree(init);
+	return;
+}
+
 static __init int svm_hardware_setup(void)
 {
 	int cpu;
@@ -966,6 +1071,8 @@ static __init int svm_hardware_setup(void)
 		kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE);
 	}
 
+	sev_hardware_setup();
+
 	for_each_possible_cpu(cpu) {
 		r = svm_cpu_init(cpu);
 		if (r)
@@ -1003,10 +1110,25 @@ err:
 	return r;
 }
 
+static __exit void sev_hardware_unsetup(void)
+{
+	int ret, psp_ret;
+
+	ret = psp_platform_shutdown(&psp_ret);
+	if (ret)
+		printk(KERN_ERR "failed to shutdown PSP rc=%d (%#0x10x)\n",
+		ret, psp_ret);
+
+	kfree(sev_asid_bitmap);
+}
+
 static __exit void svm_hardware_unsetup(void)
 {
 	int cpu;
 
+	if (sev_enabled)
+		sev_hardware_unsetup();
+
 	for_each_possible_cpu(cpu)
 		svm_cpu_uninit(cpu);
 
@@ -1088,6 +1210,11 @@ static void avic_init_vmcb(struct vcpu_svm *svm)
 	svm->vcpu.arch.apicv_active = true;
 }
 
+static void sev_init_vmcb(struct vcpu_svm *svm)
+{
+	svm->vmcb->control.nested_ctl |= SVM_NESTED_CTL_SEV_ENABLE;
+}
+
 static void init_vmcb(struct vcpu_svm *svm)
 {
 	struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1202,6 +1329,10 @@ static void init_vmcb(struct vcpu_svm *svm)
 	if (avic)
 		avic_init_vmcb(svm);
 
+	if (svm_sev_guest())
+		sev_init_vmcb(svm);
+
+
 	mark_all_dirty(svm->vmcb);
 
 	enable_gif(svm);
@@ -1413,6 +1544,14 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 		avic_update_vapic_bar(svm, APIC_DEFAULT_PHYS_BASE);
 }
 
+static void sev_init_vcpu(struct vcpu_svm *svm)
+{
+	if (!svm_sev_guest())
+		return;
+
+	svm_sev_ref();
+}
+
 static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
 {
 	struct vcpu_svm *svm;
@@ -1475,6 +1614,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
 	init_vmcb(svm);
 
 	svm_init_osvw(&svm->vcpu);
+	sev_init_vcpu(svm);
 
 	return &svm->vcpu;
 
@@ -1494,6 +1634,23 @@ out:
 	return ERR_PTR(err);
 }
 
+static void sev_uninit_vcpu(struct vcpu_svm *svm)
+{
+	int cpu;
+	int asid = svm_sev_asid();
+	struct svm_cpu_data *sd;
+
+	if (!svm_sev_guest())
+		return;
+
+	svm_sev_unref();
+
+	for_each_possible_cpu(cpu) {
+		sd = per_cpu(svm_data, cpu);
+		sd->sev_vmcb[asid] = NULL;
+	}
+}
+
 static void svm_free_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -1502,6 +1659,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
 	__free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER);
 	__free_page(virt_to_page(svm->nested.hsave));
 	__free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
+	sev_uninit_vcpu(svm);
 	kvm_vcpu_uninit(vcpu);
 	kmem_cache_free(kvm_vcpu_cache, svm);
 }
@@ -1945,6 +2103,11 @@ static int pf_interception(struct vcpu_svm *svm)
 	default:
 		error_code = svm->vmcb->control.exit_info_1;
 
+		/* In SEV mode, the guest physical address will have C-bit
+		 * set. C-bit must be cleared before handling the fault.
+		 */
+		if (svm_sev_guest())
+			fault_address &= ~sme_me_mask;
 		trace_kvm_page_fault(fault_address, error_code);
 		if (!npt_enabled && kvm_event_needs_reinjection(&svm->vcpu))
 			kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
@@ -4131,12 +4294,40 @@ static void reload_tss(struct kvm_vcpu *vcpu)
 	load_TR_desc();
 }
 
+static void pre_sev_run(struct vcpu_svm *svm)
+{
+	int asid = svm_sev_asid();
+	int cpu = raw_smp_processor_id();
+	struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
+
+	/* Assign the asid allocated for this SEV guest */
+	svm->vmcb->control.asid = svm_sev_asid();
+
+	/* Flush guest TLB:
+	 * - when different VMCB for the same ASID is to be run on the
+	 *   same host CPU
+	 *   or 
+	 * - this VMCB was executed on different host cpu in previous VMRUNs.
+	 */
+	if (sd->sev_vmcb[asid] != (void *)svm->vmcb ||
+		svm->last_cpuid != cpu)
+		svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
+
+	svm->last_cpuid = cpu;
+	sd->sev_vmcb[asid] = (void *)svm->vmcb;
+
+	mark_dirty(svm->vmcb, VMCB_ASID);
+}
+
 static void pre_svm_run(struct vcpu_svm *svm)
 {
 	int cpu = raw_smp_processor_id();
 
 	struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
 
+	if (svm_sev_guest())
+		return pre_sev_run(svm);
+
 	/* FIXME: handle wraparound of asid_generation */
 	if (svm->asid_generation != sd->asid_generation)
 		new_asid(svm, sd);
@@ -4985,6 +5176,26 @@ static inline void avic_post_state_restore(struct kvm_vcpu *vcpu)
 	avic_handle_ldr_update(vcpu);
 }
 
+static int sev_asid_new(void)
+{
+	int pos;
+
+	if (!sev_enabled)
+		return -ENOTTY;
+
+	pos = find_first_zero_bit(sev_asid_bitmap, max_sev_asid);
+	if (pos >= max_sev_asid)
+		return -EBUSY;
+
+	set_bit(pos, sev_asid_bitmap);
+	return pos;
+}
+
+static void sev_asid_free(int asid)
+{
+	clear_bit(asid, sev_asid_bitmap);
+}
+
 static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 	.cpu_has_kvm_support = has_svm,
 	.disabled_by_bios = is_disabled,

^ permalink raw reply related

* [RFC PATCH v1 19/28] KVM: SVM: prepare to reserve asid for SEV guest
From: Brijesh Singh @ 2016-08-22 23:27 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

In current implementation, asid allocation starts from 1, this patch
adds a min_asid variable in svm_vcpu structure to allow starting asid
from something other than 1.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/kvm/svm.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 211be94..f010b23 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -470,6 +470,7 @@ struct svm_cpu_data {
 	u64 asid_generation;
 	u32 max_asid;
 	u32 next_asid;
+	u32 min_asid;
 	struct kvm_ldttss_desc *tss_desc;
 
 	struct page *save_area;
@@ -726,6 +727,7 @@ static int svm_hardware_enable(void)
 	sd->asid_generation = 1;
 	sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
 	sd->next_asid = sd->max_asid + 1;
+	sd->min_asid = 1;
 
 	native_store_gdt(&gdt_descr);
 	gdt = (struct desc_struct *)gdt_descr.address;
@@ -1887,7 +1889,7 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
 {
 	if (sd->next_asid > sd->max_asid) {
 		++sd->asid_generation;
-		sd->next_asid = 1;
+		sd->next_asid = sd->min_asid;
 		svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
 	}
 

^ permalink raw reply related

* [RFC PATCH v1 26/28] KVM: SVM: add KVM_SEV_DEBUG_DECRYPT command
From: Brijesh Singh @ 2016-08-22 23:29 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

The command decrypts a page of guest memory for debugging purposes.

For more information see [1], section 7.1

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/kvm/svm.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 63e7d15..b383bc7 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -5606,6 +5606,84 @@ err_1:
 	return ret;
 }
 
+static int __sev_dbg_decrypt_page(struct kvm *kvm, unsigned long src,
+				  void *dst, int *psp_ret)
+{
+	int ret, pinned;
+	struct page **inpages;
+	struct psp_data_dbg *decrypt;
+
+	decrypt = kzalloc(sizeof(*decrypt), GFP_KERNEL);
+	if (!decrypt)
+		return -ENOMEM;
+
+	ret = -ENOMEM;
+	inpages = kzalloc(1 * sizeof(struct page *), GFP_KERNEL);
+	if (!inpages)
+		goto err_1;
+
+	/* pin the user virtual address */
+	ret = -EFAULT;
+	down_read(&current->mm->mmap_sem);
+	pinned = get_user_pages(src, 1, 1, 0, inpages, NULL);
+	up_read(&current->mm->mmap_sem);
+	if (pinned < 0)
+		goto err_2;
+
+	decrypt->hdr.buffer_len = sizeof(*decrypt);
+	decrypt->handle = kvm_sev_handle();
+	decrypt->dst_addr = __pa(dst) | sme_me_mask;
+	decrypt->src_addr = __sev_page_pa(inpages[0]);
+	decrypt->length = PAGE_SIZE;
+
+	ret = psp_dbg_decrypt(decrypt, psp_ret);
+	if (ret)
+		printk(KERN_ERR "SEV: DEBUG_DECRYPT %d (%#010x)\n",
+				ret, *psp_ret);
+	release_pages(inpages, 1, 0);
+err_2:
+	kfree(inpages);
+err_1:
+	kfree(decrypt);
+	return ret;
+}
+
+static int sev_dbg_decrypt(struct kvm *kvm,
+			   struct kvm_sev_dbg_decrypt __user *argp,
+			   int *psp_ret)
+{
+	void *data;
+	int ret, offset, len;
+	struct kvm_sev_dbg_decrypt debug;
+
+	if (!kvm_sev_guest())
+		return -ENOTTY;
+
+	if (copy_from_user(&debug, argp, sizeof(*argp)))
+		return -EFAULT;
+
+	if (debug.length > PAGE_SIZE)
+		return -EINVAL;
+
+	data = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* decrypt one page */
+	ret = __sev_dbg_decrypt_page(kvm, debug.src_addr, data, psp_ret);
+	if (ret)
+		goto err_1;
+
+	/* we have decrypted full page but copy request length */
+	offset = debug.src_addr & (PAGE_SIZE - 1);
+	len = min_t(size_t, (PAGE_SIZE - offset), debug.length);
+	if (copy_to_user((uint8_t *)debug.dst_addr, data + offset, len))
+		ret = -EFAULT;
+err_1:
+	free_page((unsigned long)data);
+	return ret;
+}
+
 static int amd_sev_issue_cmd(struct kvm *kvm,
 			     struct kvm_sev_issue_cmd __user *user_data)
 {
@@ -5636,6 +5714,11 @@ static int amd_sev_issue_cmd(struct kvm *kvm,
 					&arg.ret_code);
 		break;
 	}
+	case KVM_SEV_DBG_DECRYPT: {
+		r = sev_dbg_decrypt(kvm, (void *)arg.opaque,
+					&arg.ret_code);
+		break;
+	}
 	default:
 		break;
 	}

^ permalink raw reply related

* [RFC PATCH v1 05/28] KVM: SVM: prepare for new bit definition in nested_ctl
From: Brijesh Singh @ 2016-08-22 23:24 UTC (permalink / raw)
  To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
	linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
	aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
	mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
	jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
	mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>

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

Currently the nested_ctl variable in the vmcb_control_area structure is
used to indicate nested paging support. The nested paging support field
is actually defined as bit 0 of the this field. In order to support a new
feature flag the usage of the nested_ctl and nested paging support must
be converted to operate on a single bit.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/svm.h |    2 ++
 arch/x86/kvm/svm.c         |    7 ++++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 14824fc..2aca535 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -136,6 +136,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
 #define SVM_VM_CR_SVM_LOCK_MASK 0x0008ULL
 #define SVM_VM_CR_SVM_DIS_MASK  0x0010ULL
 
+#define SVM_NESTED_CTL_NP_ENABLE	BIT(0)
+
 struct __attribute__ ((__packed__)) vmcb_seg {
 	u16 selector;
 	u16 attrib;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 9b2de7c..9b59260 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1177,7 +1177,7 @@ static void init_vmcb(struct vcpu_svm *svm)
 
 	if (npt_enabled) {
 		/* Setup VMCB for Nested Paging */
-		control->nested_ctl = 1;
+		control->nested_ctl |= SVM_NESTED_CTL_NP_ENABLE;
 		clr_intercept(svm, INTERCEPT_INVLPG);
 		clr_exception_intercept(svm, PF_VECTOR);
 		clr_cr_intercept(svm, INTERCEPT_CR3_READ);
@@ -2701,7 +2701,8 @@ static bool nested_vmcb_checks(struct vmcb *vmcb)
 	if (vmcb->control.asid == 0)
 		return false;
 
-	if (vmcb->control.nested_ctl && !npt_enabled)
+	if ((vmcb->control.nested_ctl & SVM_NESTED_CTL_NP_ENABLE) &&
+	    !npt_enabled)
 		return false;
 
 	return true;
@@ -2776,7 +2777,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
 	else
 		svm->vcpu.arch.hflags &= ~HF_HIF_MASK;
 
-	if (nested_vmcb->control.nested_ctl) {
+	if (nested_vmcb->control.nested_ctl & SVM_NESTED_CTL_NP_ENABLE) {
 		kvm_mmu_unload(&svm->vcpu);
 		svm->nested.nested_cr3 = nested_vmcb->control.nested_cr3;
 		nested_svm_init_mmu_context(&svm->vcpu);

^ permalink raw reply related

* Re: [RFC PATCH v1 18/28] crypto: add AMD Platform Security Processor driver
From: Herbert Xu @ 2016-08-23  7:14 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: simon.guinot, linux-efi, kvm, rkrcmar, matt, linus.walleij,
	linux-mm, paul.gortmaker, hpa, dan.j.williams, aarcange, sfr,
	andriy.shevchenko, bhe, xemul, joro, x86, mingo, msalter,
	ross.zwisler, bp, dyoung, thomas.lendacky, jroedel, keescook,
	toshi.kani, mathieu.desnoyers, devel, tglx, mchehab,
	iamjoonsoo.kim, labbott, tony.luck, alexandre.bounine,
	kuleshovmail, linux-kernel, mcgrof, linux-crypto, pbonzin
In-Reply-To: <147190844204.9523.14931918358168729826.stgit@brijesh-build-machine>

On Mon, Aug 22, 2016 at 07:27:22PM -0400, Brijesh Singh wrote:
> The driver to communicate with Secure Encrypted Virtualization (SEV)
> firmware running within the AMD secure processor providing a secure key
> management interface for SEV guests.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>

This driver doesn't seem to hook into the Crypto API at all, is
there any reason why it should be in drivers/crypto?

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [PATCH] crypto: FIPS - allow RSA keys >= 2048 bits
From: Stephan Mueller @ 2016-08-23  8:09 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto

With a public notification, NIST now allows the use of RSA keys with a
modulus >= 2048 bits. The new rule allows any modulus size >= 2048 bits
provided that either 2048 or 3072 bits are supported at least so that
the entire RSA implementation can be CAVS tested.

This patch fixes the inability to boot the kernel in FIPS mode, because
certs/x509.genkey defines a 4096 bit RSA key per default. This key causes
the RSA signature verification to fail in FIPS mode without the patch
below.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/rsa_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index 4df6451..0b66dc8 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -35,8 +35,8 @@ int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
 			n_sz--;
 		}
 
-		/* In FIPS mode only allow key size 2K & 3K */
-		if (n_sz != 256 && n_sz != 384) {
+		/* In FIPS mode only allow key size 2K and higher */
+		if (n_sz < 256) {
 			pr_err("RSA: key size not allowed in FIPS mode\n");
 			return -EINVAL;
 		}
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v2] crypto: XTS - remove test that will fail in FIPS mode
From: Herbert Xu @ 2016-08-23  9:47 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: Tapas Sarangi, linux-crypto@vger.kernel.org
In-Reply-To: <16370043.OYgDIDmMpM@tauon.atsec.com>

On Tue, Aug 16, 2016 at 11:38:00AM +0200, Stephan Mueller wrote:
> Hi Tapas,
> 
> I was able to reproduce the issue now.
> 
> I tested the patch below and it works for me now. Yet, I see that dracut-fips seems to need some fixes too as it cannot find cmac when compiled as module and has some issues with the authenc() ciphers too.
> 
> 
> ---8<---
>  
> In FIPS mode, setting XTS keys where the AES key is identical to the
> tweak key is forbidden. Thus, the self test with such property will fail
> in FIPS mode.
> 
> As we have other tests available for XTS, this patch simply removes the
> offending test vectors.
> 
> Reported-by: Tapas Sarangi <TSarangi@trustwave.com>
> Signed-off-by: Stephan Mueller <stephan.mueller@atsec.com>

We should fix this without removing tests.  Perhaps add a field
in the vector to indicate that it should be skipped when in FIPS
mode, just like we do for expected weak keys.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Crypto Fixes for 4.8
From: Herbert Xu @ 2016-08-23  9:51 UTC (permalink / raw)
  To: Linus Torvalds, David S. Miller, Linux Kernel Mailing List,
	Linux Crypto Mailing List
In-Reply-To: <20160801095821.GA1260@gondor.apana.org.au>

Hi Linus:

This push fixes a number of memory corruption bugs in the newly
added sha256-mb/sha256-mb code.

Please pull from

git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git linus


Xiaodong Liu (2):
      crypto: sha256-mb - fix ctx pointer and digest copy
      crypto: sha512-mb - fix ctx pointer

 arch/x86/crypto/sha256-mb/sha256_mb.c                |    4 ++--
 arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S |    7 ++++---
 arch/x86/crypto/sha512-mb/sha512_mb.c                |    4 ++--
 3 files changed, 8 insertions(+), 7 deletions(-)

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH V2 linux-next] hwrng: update Freescale i.MX RNGA Random Number Generator
From: Arnd Bergmann @ 2016-08-23 12:27 UTC (permalink / raw)
  To: Fabian Frederick; +Cc: Matt Mackall, Herbert Xu, linux-crypto, linux-kernel
In-Reply-To: <1471376985-7791-1-git-send-email-fabf@skynet.be>

On Tuesday, August 16, 2016 9:49:45 PM CEST Fabian Frederick wrote:
> We can directly depend on SOC_IMX31 since commit c9ee94965dce
> ("ARM: imx: deconstruct mxc_rnga initialization")
> 
> Since that commit, CONFIG_HW_RANDOM_MXC_RNGA could not be switched on
> with unknown symbol ARCH_HAS_RNGA and mxc-rnga.o can't be generated with
> ARCH=arm make M=drivers/char/hw_random
> Previously, HW_RANDOM_MXC_RNGA required ARCH_HAS_RNGA
> which was based on IMX_HAVE_PLATFORM_MXC_RNGA  && ARCH_MXC.
> IMX_HAVE_PLATFORM_MXC_RNGA  was based on SOC_IMX31.
> 
> Fixes: c9ee94965dce ("ARM: imx: deconstruct mxc_rnga initialization")
> Signed-off-by: Fabian Frederick <fabf@skynet.be>
> ---
> -Cc to linux-crypto (suggested by Herbert Xu)
> -Adding "Fixes:" (suggested by Arnd Bergmann)
> -This patch appeared in 4.8-rc1 (not in stable yet)
> -Improving patch description
> 

Thanks for fixing my mistake!

Acked-by: Arnd Bergmann <arnd@arndb.de>

^ permalink raw reply

* Re: [PATCH -next v2] crypto: sun4i-ss - fix missing unlock on error in sun4i_hash()
From: Corentin LABBE @ 2016-08-23 13:54 UTC (permalink / raw)
  To: Wei Yongjun, Herbert Xu, David S. Miller, Maxime Ripard,
	Chen-Yu Tsai
  Cc: linux-crypto, linux-arm-kernel
In-Reply-To: <1471690133-24396-1-git-send-email-weiyj.lk@gmail.com>

On 20/08/2016 12:48, Wei Yongjun wrote:
> Add the missing unlock before return from function sun4i_hash()
> in the error handling case.
> 
> Fixes: 477d9b2e591b ("crypto: sun4i-ss - unify update/final function")
> Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
> ---
> v1 -> v2: goto release_ss as LABBE Corentin's suggestion
> ---
>  drivers/crypto/sunxi-ss/sun4i-ss-hash.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
> index 2ee3b59..1afeb8e 100644
> --- a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
> +++ b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
> @@ -245,7 +245,8 @@ int sun4i_hash(struct ahash_request *areq)
>  		if (end > areq->nbytes || areq->nbytes - end > 63) {
>  			dev_err(ss->dev, "ERROR: Bound error %u %u\n",
>  				end, areq->nbytes);
> -			return -EINVAL;
> +			err = -EINVAL;
> +			goto release_ss;
>  		}
>  	} else {
>  		/* Since we have the flag final, we can go up to modulo 4 */
> 

Acked-by: Corentin LABBE <clabbe.montjoie@gmail.com>

Thanks

^ permalink raw reply

* [PATCH] crypto: rockchip - use devm_add_action_or_reset()
From: Sudip Mukherjee @ 2016-08-23 14:58 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Heiko Stuebner
  Cc: linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sudip Mukherjee,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA

If devm_add_action() fails we are explicitly calling the cleanup to free
the resources allocated.  Lets use the helper devm_add_action_or_reset()
and return directly in case of error, as we know that the cleanup function
has been already called by the helper if there was any error.

Signed-off-by: Sudip Mukherjee <sudip.mukherjee-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
---
 drivers/crypto/rockchip/rk3288_crypto.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c
index af50825..d0f80c6 100644
--- a/drivers/crypto/rockchip/rk3288_crypto.c
+++ b/drivers/crypto/rockchip/rk3288_crypto.c
@@ -304,11 +304,9 @@ static int rk_crypto_probe(struct platform_device *pdev)
 	usleep_range(10, 20);
 	reset_control_deassert(crypto_info->rst);
 
-	err = devm_add_action(dev, rk_crypto_action, crypto_info);
-	if (err) {
-		reset_control_assert(crypto_info->rst);
+	err = devm_add_action_or_reset(dev, rk_crypto_action, crypto_info);
+	if (err)
 		goto err_crypto;
-	}
 
 	spin_lock_init(&crypto_info->lock);
 
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] crypto: rockchip - use devm_add_action_or_reset()
From: Heiko Stübner @ 2016-08-23 15:34 UTC (permalink / raw)
  To: Sudip Mukherjee
  Cc: Herbert Xu, linux-kernel, linux-rockchip, linux-crypto,
	David S. Miller, linux-arm-kernel
In-Reply-To: <1471964334-27060-1-git-send-email-sudipm.mukherjee@gmail.com>

Am Dienstag, 23. August 2016, 20:28:54 schrieb Sudip Mukherjee:
> If devm_add_action() fails we are explicitly calling the cleanup to free
> the resources allocated.  Lets use the helper devm_add_action_or_reset()
> and return directly in case of error, as we know that the cleanup function
> has been already called by the helper if there was any error.
> 
> Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>

nice little cleanup
Reviewed-by: Heiko Stuebner <heiko@sntech.de>

^ permalink raw reply

* crypto: mxs-dcp: do not call blocking ops when !TASK_RUNNING; state=1
From: Stefan Wahren @ 2016-08-23 20:38 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto, Fabio Estevam

Hi,

i'm using a iMX233-OLinuXino board and i get the following warning during boot
with 4.8.0-rc2-next-20160819:

[    2.450000] ------------[ cut here ]------------
[    2.450000] WARNING: CPU: 0 PID: 42 at kernel/sched/core.c:7602
__might_sleep+0x8c/0xa0
[    2.470000] do not call blocking ops when !TASK_RUNNING; state=1 set at
[<c048f730>] dcp_chan_thread_aes+0x24/0x664
[    2.480000] Modules linked in:
[    2.480000] CPU: 0 PID: 42 Comm: mxs_dcp_chan/ae Not tainted
4.8.0-rc2-next-20160819-dirty #2
[    2.490000] mxs-dcp 80028000.dcp: Failed to register sha1 hash!
[    2.500000] Hardware name: Freescale MXS (Device Tree)
[    2.510000] [<c00100a4>] (unwind_backtrace) from [<c000e088>]
(show_stack+0x10/0x14)
[    2.520000] [<c000e088>] (show_stack) from [<c001ce8c>] (__warn+0xd8/0x100)
[    2.530000] [<c001ce8c>] (__warn) from [<c001cf5c>]
(warn_slowpath_fmt+0x38/0x48)
[    2.540000] [<c001cf5c>] (warn_slowpath_fmt) from [<c00479dc>]
(__might_sleep+0x8c/0xa0)
[    2.540000] [<c00479dc>] (__might_sleep) from [<c05dd24c>]
(mutex_lock_nested+0x24/0x39c)
[    2.550000] [<c05dd24c>] (mutex_lock_nested) from [<c048f760>]
(dcp_chan_thread_aes+0x54/0x664)
[    2.560000] [<c048f760>] (dcp_chan_thread_aes) from [<c0040574>]
(kthread+0xd0/0xf0)
[    2.580000] [<c0040574>] (kthread) from [<c000a36c>]
(ret_from_fork+0x14/0x28)
[    2.590000] ---[ end trace e2182161e464af25 ]---

What would be the right fix for this issue?

Regards
Stefan

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox