hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
kernel/arch/x86/kernel/head64.c
....@@ -20,13 +20,13 @@
2020 #include <linux/io.h>
2121 #include <linux/memblock.h>
2222 #include <linux/mem_encrypt.h>
23
+#include <linux/pgtable.h>
2324
2425 #include <asm/processor.h>
2526 #include <asm/proto.h>
2627 #include <asm/smp.h>
2728 #include <asm/setup.h>
2829 #include <asm/desc.h>
29
-#include <asm/pgtable.h>
3030 #include <asm/tlbflush.h>
3131 #include <asm/sections.h>
3232 #include <asm/kdebug.h>
....@@ -36,6 +36,11 @@
3636 #include <asm/microcode.h>
3737 #include <asm/kasan.h>
3838 #include <asm/fixmap.h>
39
+#include <asm/realmode.h>
40
+#include <asm/desc.h>
41
+#include <asm/extable.h>
42
+#include <asm/trapnr.h>
43
+#include <asm/sev-es.h>
3944
4045 /*
4146 * Manage page tables very early on.
....@@ -61,7 +66,25 @@
6166 EXPORT_SYMBOL(vmemmap_base);
6267 #endif
6368
64
-#define __head __section(.head.text)
69
+/*
70
+ * GDT used on the boot CPU before switching to virtual addresses.
71
+ */
72
+static struct desc_struct startup_gdt[GDT_ENTRIES] = {
73
+ [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
74
+ [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
75
+ [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
76
+};
77
+
78
+/*
79
+ * Address needs to be set at runtime because it references the startup_gdt
80
+ * while the kernel still uses a direct mapping.
81
+ */
82
+static struct desc_ptr startup_gdt_descr = {
83
+ .size = sizeof(startup_gdt),
84
+ .address = 0,
85
+};
86
+
87
+#define __head __section(".head.text")
6588
6689 static void __head *fixup_pointer(void *ptr, unsigned long physaddr)
6790 {
....@@ -297,7 +320,7 @@
297320 }
298321
299322 /* Create a new PMD entry */
300
-int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
323
+bool __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
301324 {
302325 unsigned long physaddr = address - __PAGE_OFFSET;
303326 pgdval_t pgd, *pgd_p;
....@@ -307,7 +330,7 @@
307330
308331 /* Invalid address or early pgt is done ? */
309332 if (physaddr >= MAXMEM || read_cr3_pa() != __pa_nodebug(early_top_pgt))
310
- return -1;
333
+ return false;
311334
312335 again:
313336 pgd_p = &early_top_pgt[pgd_index(address)].pgd;
....@@ -364,10 +387,10 @@
364387 }
365388 pmd_p[pmd_index(address)] = pmd;
366389
367
- return 0;
390
+ return true;
368391 }
369392
370
-int __init early_make_pgtable(unsigned long address)
393
+static bool __init early_make_pgtable(unsigned long address)
371394 {
372395 unsigned long physaddr = address - __PAGE_OFFSET;
373396 pmdval_t pmd;
....@@ -377,12 +400,27 @@
377400 return __early_make_pgtable(address, pmd);
378401 }
379402
403
+void __init do_early_exception(struct pt_regs *regs, int trapnr)
404
+{
405
+ if (trapnr == X86_TRAP_PF &&
406
+ early_make_pgtable(native_read_cr2()))
407
+ return;
408
+
409
+ if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT) &&
410
+ trapnr == X86_TRAP_VC && handle_vc_boot_ghcb(regs))
411
+ return;
412
+
413
+ early_fixup_exception(regs, trapnr);
414
+}
415
+
380416 /* Don't add a printk in there. printk relies on the PDA which is not initialized
381417 yet. */
382418 static void __init clear_bss(void)
383419 {
384420 memset(__bss_start, 0,
385421 (unsigned long) __bss_stop - (unsigned long) __bss_start);
422
+ memset(__brk_base, 0,
423
+ (unsigned long) __brk_limit - (unsigned long) __brk_base);
386424 }
387425
388426 static unsigned long get_cmd_line_ptr(void)
....@@ -405,7 +443,7 @@
405443 */
406444 sme_map_bootdata(real_mode_data);
407445
408
- memcpy(&boot_params, real_mode_data, sizeof boot_params);
446
+ memcpy(&boot_params, real_mode_data, sizeof(boot_params));
409447 sanitize_boot_params(&boot_params);
410448 cmd_line_ptr = get_cmd_line_ptr();
411449 if (cmd_line_ptr) {
....@@ -489,3 +527,81 @@
489527
490528 start_kernel();
491529 }
530
+
531
+/*
532
+ * Data structures and code used for IDT setup in head_64.S. The bringup-IDT is
533
+ * used until the idt_table takes over. On the boot CPU this happens in
534
+ * x86_64_start_kernel(), on secondary CPUs in start_secondary(). In both cases
535
+ * this happens in the functions called from head_64.S.
536
+ *
537
+ * The idt_table can't be used that early because all the code modifying it is
538
+ * in idt.c and can be instrumented by tracing or KASAN, which both don't work
539
+ * during early CPU bringup. Also the idt_table has the runtime vectors
540
+ * configured which require certain CPU state to be setup already (like TSS),
541
+ * which also hasn't happened yet in early CPU bringup.
542
+ */
543
+static gate_desc bringup_idt_table[NUM_EXCEPTION_VECTORS] __page_aligned_data;
544
+
545
+static struct desc_ptr bringup_idt_descr = {
546
+ .size = (NUM_EXCEPTION_VECTORS * sizeof(gate_desc)) - 1,
547
+ .address = 0, /* Set at runtime */
548
+};
549
+
550
+static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler)
551
+{
552
+#ifdef CONFIG_AMD_MEM_ENCRYPT
553
+ struct idt_data data;
554
+ gate_desc desc;
555
+
556
+ init_idt_data(&data, n, handler);
557
+ idt_init_desc(&desc, &data);
558
+ native_write_idt_entry(idt, n, &desc);
559
+#endif
560
+}
561
+
562
+/* This runs while still in the direct mapping */
563
+static void startup_64_load_idt(unsigned long physbase)
564
+{
565
+ struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase);
566
+ gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);
567
+
568
+
569
+ if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) {
570
+ void *handler;
571
+
572
+ /* VMM Communication Exception */
573
+ handler = fixup_pointer(vc_no_ghcb, physbase);
574
+ set_bringup_idt_handler(idt, X86_TRAP_VC, handler);
575
+ }
576
+
577
+ desc->address = (unsigned long)idt;
578
+ native_load_idt(desc);
579
+}
580
+
581
+/* This is used when running on kernel addresses */
582
+void early_setup_idt(void)
583
+{
584
+ /* VMM Communication Exception */
585
+ if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT))
586
+ set_bringup_idt_handler(bringup_idt_table, X86_TRAP_VC, vc_boot_ghcb);
587
+
588
+ bringup_idt_descr.address = (unsigned long)bringup_idt_table;
589
+ native_load_idt(&bringup_idt_descr);
590
+}
591
+
592
+/*
593
+ * Setup boot CPU state needed before kernel switches to virtual addresses.
594
+ */
595
+void __head startup_64_setup_env(unsigned long physbase)
596
+{
597
+ /* Load GDT */
598
+ startup_gdt_descr.address = (unsigned long)fixup_pointer(startup_gdt, physbase);
599
+ native_load_gdt(&startup_gdt_descr);
600
+
601
+ /* New GDT is live - reload data segment registers */
602
+ asm volatile("movl %%eax, %%ds\n"
603
+ "movl %%eax, %%ss\n"
604
+ "movl %%eax, %%es\n" : : "a"(__KERNEL_DS) : "memory");
605
+
606
+ startup_64_load_idt(physbase);
607
+}