x86/sev-es: Setup an early #VC handler
[linux-2.6-microblaze.git] / arch / x86 / kernel / head64.c
index 7bfd5c2..fc55cc9 100644 (file)
@@ -38,6 +38,9 @@
 #include <asm/fixmap.h>
 #include <asm/realmode.h>
 #include <asm/desc.h>
+#include <asm/extable.h>
+#include <asm/trapnr.h>
+#include <asm/sev-es.h>
 
 /*
  * Manage page tables very early on.
@@ -317,7 +320,7 @@ static void __init reset_early_page_tables(void)
 }
 
 /* Create a new PMD entry */
-int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
+bool __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
 {
        unsigned long physaddr = address - __PAGE_OFFSET;
        pgdval_t pgd, *pgd_p;
@@ -327,7 +330,7 @@ int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
 
        /* Invalid address or early pgt is done ?  */
        if (physaddr >= MAXMEM || read_cr3_pa() != __pa_nodebug(early_top_pgt))
-               return -1;
+               return false;
 
 again:
        pgd_p = &early_top_pgt[pgd_index(address)].pgd;
@@ -384,10 +387,10 @@ again:
        }
        pmd_p[pmd_index(address)] = pmd;
 
-       return 0;
+       return true;
 }
 
-int __init early_make_pgtable(unsigned long address)
+static bool __init early_make_pgtable(unsigned long address)
 {
        unsigned long physaddr = address - __PAGE_OFFSET;
        pmdval_t pmd;
@@ -397,6 +400,15 @@ int __init early_make_pgtable(unsigned long address)
        return __early_make_pgtable(address, pmd);
 }
 
+void __init do_early_exception(struct pt_regs *regs, int trapnr)
+{
+       if (trapnr == X86_TRAP_PF &&
+           early_make_pgtable(native_read_cr2()))
+               return;
+
+       early_fixup_exception(regs, trapnr);
+}
+
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
 static void __init clear_bss(void)
@@ -529,12 +541,34 @@ static struct desc_ptr bringup_idt_descr = {
        .address        = 0, /* Set at runtime */
 };
 
+static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler)
+{
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+       struct idt_data data;
+       gate_desc desc;
+
+       init_idt_data(&data, n, handler);
+       idt_init_desc(&desc, &data);
+       native_write_idt_entry(idt, n, &desc);
+#endif
+}
+
 /* This runs while still in the direct mapping */
 static void startup_64_load_idt(unsigned long physbase)
 {
        struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase);
+       gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);
+
+
+       if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) {
+               void *handler;
+
+               /* VMM Communication Exception */
+               handler = fixup_pointer(vc_no_ghcb, physbase);
+               set_bringup_idt_handler(idt, X86_TRAP_VC, handler);
+       }
 
-       desc->address = (unsigned long)fixup_pointer(bringup_idt_table, physbase);
+       desc->address = (unsigned long)idt;
        native_load_idt(desc);
 }