--- /dev/null
+From 107cd2532181b96c549e8f224cdcca8631c3076b Mon Sep 17 00:00:00 2001
+From: Tom Lendacky <thomas.lendacky@amd.com>
+Date: Wed, 10 Jan 2018 13:26:34 -0600
+Subject: x86/mm: Encrypt the initrd earlier for BSP microcode update
+
+From: Tom Lendacky <thomas.lendacky@amd.com>
+
+commit 107cd2532181b96c549e8f224cdcca8631c3076b upstream.
+
+Currently the BSP microcode update code examines the initrd very early
+in the boot process. If SME is active, the initrd is treated as being
+encrypted but it has not been encrypted (in place) yet. Update the
+early boot code that encrypts the kernel to also encrypt the initrd so
+that early BSP microcode updates work.
+
+Tested-by: Gabriel Craciunescu <nix.or.die@gmail.com>
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Reviewed-by: Borislav Petkov <bp@suse.de>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brijesh Singh <brijesh.singh@amd.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20180110192634.6026.10452.stgit@tlendack-t1.amdoffice.net
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/mem_encrypt.h | 4 +-
+ arch/x86/kernel/head64.c | 4 +-
+ arch/x86/kernel/setup.c | 8 ----
+ arch/x86/mm/mem_encrypt.c | 66 ++++++++++++++++++++++++++++++++-----
+ arch/x86/mm/mem_encrypt_boot.S | 46 ++++++++++++-------------
+ 5 files changed, 85 insertions(+), 43 deletions(-)
+
+--- a/arch/x86/include/asm/mem_encrypt.h
++++ b/arch/x86/include/asm/mem_encrypt.h
+@@ -39,7 +39,7 @@ void __init sme_unmap_bootdata(char *rea
+
+ void __init sme_early_init(void);
+
+-void __init sme_encrypt_kernel(void);
++void __init sme_encrypt_kernel(struct boot_params *bp);
+ void __init sme_enable(struct boot_params *bp);
+
+ /* Architecture __weak replacement functions */
+@@ -61,7 +61,7 @@ static inline void __init sme_unmap_boot
+
+ static inline void __init sme_early_init(void) { }
+
+-static inline void __init sme_encrypt_kernel(void) { }
++static inline void __init sme_encrypt_kernel(struct boot_params *bp) { }
+ static inline void __init sme_enable(struct boot_params *bp) { }
+
+ #endif /* CONFIG_AMD_MEM_ENCRYPT */
+--- a/arch/x86/kernel/head64.c
++++ b/arch/x86/kernel/head64.c
+@@ -157,8 +157,8 @@ unsigned long __head __startup_64(unsign
+ p = fixup_pointer(&phys_base, physaddr);
+ *p += load_delta - sme_get_me_mask();
+
+- /* Encrypt the kernel (if SME is active) */
+- sme_encrypt_kernel();
++ /* Encrypt the kernel and related (if SME is active) */
++ sme_encrypt_kernel(bp);
+
+ /*
+ * Return the SME encryption mask (if SME is active) to be used as a
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -376,14 +376,6 @@ static void __init reserve_initrd(void)
+ !ramdisk_image || !ramdisk_size)
+ return; /* No initrd provided by bootloader */
+
+- /*
+- * 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.
+- */
+- sme_early_encrypt(ramdisk_image, ramdisk_end - ramdisk_image);
+-
+ initrd_start = 0;
+
+ mapped_size = memblock_mem_size(max_pfn_mapped);
+--- a/arch/x86/mm/mem_encrypt.c
++++ b/arch/x86/mm/mem_encrypt.c
+@@ -487,11 +487,12 @@ static unsigned long __init sme_pgtable_
+ return total;
+ }
+
+-void __init sme_encrypt_kernel(void)
++void __init sme_encrypt_kernel(struct boot_params *bp)
+ {
+ unsigned long workarea_start, workarea_end, workarea_len;
+ unsigned long execute_start, execute_end, execute_len;
+ unsigned long kernel_start, kernel_end, kernel_len;
++ unsigned long initrd_start, initrd_end, initrd_len;
+ struct sme_populate_pgd_data ppd;
+ unsigned long pgtable_area_len;
+ unsigned long decrypted_base;
+@@ -500,14 +501,15 @@ void __init sme_encrypt_kernel(void)
+ return;
+
+ /*
+- * Prepare for encrypting the kernel by building new pagetables with
+- * the necessary attributes needed to encrypt the kernel in place.
++ * Prepare for encrypting the kernel and initrd by building new
++ * pagetables with the necessary attributes needed to encrypt the
++ * kernel in place.
+ *
+ * One range of virtual addresses will map the memory occupied
+- * by the kernel as encrypted.
++ * by the kernel and initrd as encrypted.
+ *
+ * Another range of virtual addresses will map the memory occupied
+- * by the kernel as decrypted and write-protected.
++ * by the kernel and initrd as decrypted and write-protected.
+ *
+ * The use of write-protect attribute will prevent any of the
+ * memory from being cached.
+@@ -518,6 +520,20 @@ void __init sme_encrypt_kernel(void)
+ kernel_end = ALIGN(__pa_symbol(_end), PMD_PAGE_SIZE);
+ kernel_len = kernel_end - kernel_start;
+
++ initrd_start = 0;
++ initrd_end = 0;
++ initrd_len = 0;
++#ifdef CONFIG_BLK_DEV_INITRD
++ initrd_len = (unsigned long)bp->hdr.ramdisk_size |
++ ((unsigned long)bp->ext_ramdisk_size << 32);
++ if (initrd_len) {
++ initrd_start = (unsigned long)bp->hdr.ramdisk_image |
++ ((unsigned long)bp->ext_ramdisk_image << 32);
++ initrd_end = PAGE_ALIGN(initrd_start + initrd_len);
++ initrd_len = initrd_end - initrd_start;
++ }
++#endif
++
+ /* Set the encryption workarea to be immediately after the kernel */
+ workarea_start = kernel_end;
+
+@@ -540,6 +556,8 @@ void __init sme_encrypt_kernel(void)
+ */
+ pgtable_area_len = sizeof(pgd_t) * PTRS_PER_PGD;
+ pgtable_area_len += sme_pgtable_calc(execute_end - kernel_start) * 2;
++ if (initrd_len)
++ pgtable_area_len += sme_pgtable_calc(initrd_len) * 2;
+
+ /* PUDs and PMDs needed in the current pagetables for the workarea */
+ pgtable_area_len += sme_pgtable_calc(execute_len + pgtable_area_len);
+@@ -578,9 +596,9 @@ void __init sme_encrypt_kernel(void)
+
+ /*
+ * A new pagetable structure is being built to allow for the kernel
+- * to be encrypted. It starts with an empty PGD that will then be
+- * populated with new PUDs and PMDs as the encrypted and decrypted
+- * kernel mappings are created.
++ * and initrd to be encrypted. It starts with an empty PGD that will
++ * then be populated with new PUDs and PMDs as the encrypted and
++ * decrypted kernel mappings are created.
+ */
+ ppd.pgd = ppd.pgtable_area;
+ memset(ppd.pgd, 0, sizeof(pgd_t) * PTRS_PER_PGD);
+@@ -593,6 +611,12 @@ void __init sme_encrypt_kernel(void)
+ * the base of the mapping.
+ */
+ decrypted_base = (pgd_index(workarea_end) + 1) & (PTRS_PER_PGD - 1);
++ if (initrd_len) {
++ unsigned long check_base;
++
++ check_base = (pgd_index(initrd_end) + 1) & (PTRS_PER_PGD - 1);
++ decrypted_base = max(decrypted_base, check_base);
++ }
+ decrypted_base <<= PGDIR_SHIFT;
+
+ /* Add encrypted kernel (identity) mappings */
+@@ -607,6 +631,21 @@ void __init sme_encrypt_kernel(void)
+ ppd.vaddr_end = kernel_end + decrypted_base;
+ sme_map_range_decrypted_wp(&ppd);
+
++ if (initrd_len) {
++ /* Add encrypted initrd (identity) mappings */
++ ppd.paddr = initrd_start;
++ ppd.vaddr = initrd_start;
++ ppd.vaddr_end = initrd_end;
++ sme_map_range_encrypted(&ppd);
++ /*
++ * Add decrypted, write-protected initrd (non-identity) mappings
++ */
++ ppd.paddr = initrd_start;
++ ppd.vaddr = initrd_start + decrypted_base;
++ ppd.vaddr_end = initrd_end + decrypted_base;
++ sme_map_range_decrypted_wp(&ppd);
++ }
++
+ /* Add decrypted workarea mappings to both kernel mappings */
+ ppd.paddr = workarea_start;
+ ppd.vaddr = workarea_start;
+@@ -622,6 +661,11 @@ void __init sme_encrypt_kernel(void)
+ sme_encrypt_execute(kernel_start, kernel_start + decrypted_base,
+ kernel_len, workarea_start, (unsigned long)ppd.pgd);
+
++ if (initrd_len)
++ sme_encrypt_execute(initrd_start, initrd_start + decrypted_base,
++ initrd_len, workarea_start,
++ (unsigned long)ppd.pgd);
++
+ /*
+ * At this point we are running encrypted. Remove the mappings for
+ * the decrypted areas - all that is needed for this is to remove
+@@ -631,6 +675,12 @@ void __init sme_encrypt_kernel(void)
+ ppd.vaddr_end = kernel_end + decrypted_base;
+ sme_clear_pgd(&ppd);
+
++ if (initrd_len) {
++ ppd.vaddr = initrd_start + decrypted_base;
++ ppd.vaddr_end = initrd_end + decrypted_base;
++ sme_clear_pgd(&ppd);
++ }
++
+ ppd.vaddr = workarea_start + decrypted_base;
+ ppd.vaddr_end = workarea_end + decrypted_base;
+ sme_clear_pgd(&ppd);
+--- a/arch/x86/mm/mem_encrypt_boot.S
++++ b/arch/x86/mm/mem_encrypt_boot.S
+@@ -22,9 +22,9 @@ ENTRY(sme_encrypt_execute)
+
+ /*
+ * Entry parameters:
+- * RDI - virtual address for the encrypted kernel mapping
+- * RSI - virtual address for the decrypted kernel mapping
+- * RDX - length of kernel
++ * RDI - virtual address for the encrypted mapping
++ * RSI - virtual address for the decrypted mapping
++ * RDX - length to encrypt
+ * RCX - virtual address of the encryption workarea, including:
+ * - stack page (PAGE_SIZE)
+ * - encryption routine page (PAGE_SIZE)
+@@ -41,9 +41,9 @@ ENTRY(sme_encrypt_execute)
+ addq $PAGE_SIZE, %rax /* Workarea encryption routine */
+
+ push %r12
+- movq %rdi, %r10 /* Encrypted kernel */
+- movq %rsi, %r11 /* Decrypted kernel */
+- movq %rdx, %r12 /* Kernel length */
++ movq %rdi, %r10 /* Encrypted area */
++ movq %rsi, %r11 /* Decrypted area */
++ movq %rdx, %r12 /* Area length */
+
+ /* Copy encryption routine into the workarea */
+ movq %rax, %rdi /* Workarea encryption routine */
+@@ -52,10 +52,10 @@ ENTRY(sme_encrypt_execute)
+ rep movsb
+
+ /* Setup registers for call */
+- movq %r10, %rdi /* Encrypted kernel */
+- movq %r11, %rsi /* Decrypted kernel */
++ movq %r10, %rdi /* Encrypted area */
++ movq %r11, %rsi /* Decrypted area */
+ movq %r8, %rdx /* Pagetables used for encryption */
+- movq %r12, %rcx /* Kernel length */
++ movq %r12, %rcx /* Area length */
+ movq %rax, %r8 /* Workarea encryption routine */
+ addq $PAGE_SIZE, %r8 /* Workarea intermediate copy buffer */
+
+@@ -71,7 +71,7 @@ ENDPROC(sme_encrypt_execute)
+
+ ENTRY(__enc_copy)
+ /*
+- * Routine used to encrypt kernel.
++ * Routine used to encrypt memory in place.
+ * This routine must be run outside of the kernel proper since
+ * the kernel will be encrypted during the process. So this
+ * routine is defined here and then copied to an area outside
+@@ -79,19 +79,19 @@ ENTRY(__enc_copy)
+ * during execution.
+ *
+ * On entry the registers must be:
+- * RDI - virtual address for the encrypted kernel mapping
+- * RSI - virtual address for the decrypted kernel mapping
++ * RDI - virtual address for the encrypted mapping
++ * RSI - virtual address for the decrypted mapping
+ * RDX - address of the pagetables to use for encryption
+- * RCX - length of kernel
++ * RCX - length of area
+ * R8 - intermediate copy buffer
+ *
+ * RAX - points to this routine
+ *
+- * The kernel will be encrypted by copying from the non-encrypted
+- * kernel space to an intermediate buffer and then copying from the
+- * intermediate buffer back to the encrypted kernel space. The physical
+- * addresses of the two kernel space mappings are the same which
+- * results in the kernel being encrypted "in place".
++ * The area will be encrypted by copying from the non-encrypted
++ * memory space to an intermediate buffer and then copying from the
++ * intermediate buffer back to the encrypted memory space. The physical
++ * addresses of the two mappings are the same which results in the area
++ * being encrypted "in place".
+ */
+ /* Enable the new page tables */
+ mov %rdx, %cr3
+@@ -106,9 +106,9 @@ ENTRY(__enc_copy)
+ push %r15
+ push %r12
+
+- movq %rcx, %r9 /* Save kernel length */
+- movq %rdi, %r10 /* Save encrypted kernel address */
+- movq %rsi, %r11 /* Save decrypted kernel address */
++ movq %rcx, %r9 /* Save area length */
++ movq %rdi, %r10 /* Save encrypted area address */
++ movq %rsi, %r11 /* Save decrypted area address */
+
+ /* Set the PAT register PA5 entry to write-protect */
+ movl $MSR_IA32_CR_PAT, %ecx
+@@ -128,13 +128,13 @@ ENTRY(__enc_copy)
+ movq %r9, %r12
+
+ 2:
+- movq %r11, %rsi /* Source - decrypted kernel */
++ movq %r11, %rsi /* Source - decrypted area */
+ movq %r8, %rdi /* Dest - intermediate copy buffer */
+ movq %r12, %rcx
+ rep movsb
+
+ movq %r8, %rsi /* Source - intermediate copy buffer */
+- movq %r10, %rdi /* Dest - encrypted kernel */
++ movq %r10, %rdi /* Dest - encrypted area */
+ movq %r12, %rcx
+ rep movsb
+