Merge branch 'x86-kdump-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / arch / x86 / kernel / machine_kexec_64.c
index 9184037aec62f92e8bb147ef7a083c65ce6fec86..5dcd438ad8f25f85869f7a25ff34928594f4abf4 100644 (file)
@@ -123,12 +123,13 @@ static void free_transition_pgtable(struct kimage *image)
 
 static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
 {
+       pgprot_t prot = PAGE_KERNEL_EXEC_NOENC;
+       unsigned long vaddr, paddr;
+       int result = -ENOMEM;
        p4d_t *p4d;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
-       unsigned long vaddr, paddr;
-       int result = -ENOMEM;
 
        vaddr = (unsigned long)relocate_kernel;
        paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE);
@@ -165,7 +166,11 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
                set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
        }
        pte = pte_offset_kernel(pmd, vaddr);
-       set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC_NOENC));
+
+       if (sev_active())
+               prot = PAGE_KERNEL_EXEC;
+
+       set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, prot));
        return 0;
 err:
        return result;
@@ -202,6 +207,11 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
        level4p = (pgd_t *)__va(start_pgtable);
        clear_page(level4p);
 
+       if (sev_active()) {
+               info.page_flag   |= _PAGE_ENC;
+               info.kernpg_flag |= _PAGE_ENC;
+       }
+
        if (direct_gbpages)
                info.direct_gbpages = true;
 
@@ -644,8 +654,20 @@ void arch_kexec_unprotect_crashkres(void)
        kexec_mark_crashkres(false);
 }
 
+/*
+ * During a traditional boot under SME, SME will encrypt the kernel,
+ * so the SME kexec kernel also needs to be un-encrypted in order to
+ * replicate a normal SME boot.
+ *
+ * During a traditional boot under SEV, the kernel has already been
+ * loaded encrypted, so the SEV kexec kernel needs to be encrypted in
+ * order to replicate a normal SEV boot.
+ */
 int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages, gfp_t gfp)
 {
+       if (sev_active())
+               return 0;
+
        /*
         * If SME is active we need to be sure that kexec pages are
         * not encrypted because when we boot to the new kernel the
@@ -656,6 +678,9 @@ int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages, gfp_t gfp)
 
 void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages)
 {
+       if (sev_active())
+               return;
+
        /*
         * If SME is active we need to reset the pages back to being
         * an encrypted mapping before freeing them.