The branch main has been updated by imp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5e8bd45ffb416f6d4e041690e3e656fd907492bf

commit 5e8bd45ffb416f6d4e041690e3e656fd907492bf
Author:     Ahmad Khalifa <ahmadkhalifa...@gmail.com>
AuthorDate: 2024-09-27 16:08:11 +0000
Commit:     Warner Losh <i...@freebsd.org>
CommitDate: 2024-12-05 00:19:17 +0000

    stand/elf64_freebsd.c: use headers instead of doing things ourselves
    
    Try our best to use headers instead of doing things ourselves. With
    i386's headers, there are some holes we need to fill manually.
    
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/1446
---
 stand/efi/loader/arch/i386/elf64_freebsd.c | 104 ++++++++++++++++-------------
 stand/i386/libi386/elf64_freebsd.c         |  24 ++++---
 stand/userboot/userboot/elf64_freebsd.c    |  53 ++++++---------
 3 files changed, 89 insertions(+), 92 deletions(-)

diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c 
b/stand/efi/loader/arch/i386/elf64_freebsd.c
index 0dc16437d905..b02cda2269bc 100644
--- a/stand/efi/loader/arch/i386/elf64_freebsd.c
+++ b/stand/efi/loader/arch/i386/elf64_freebsd.c
@@ -28,7 +28,11 @@
 #define __ELF_WORD_SIZE 64
 #include <sys/param.h>
 #include <sys/linker.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
 #include <machine/elf.h>
+#include <machine/pmap_pae.h>
+#include <machine/segments.h>
 
 #include <efi.h>
 #include <efilib.h>
@@ -56,35 +60,14 @@ struct file_format *file_formats[] = {
        NULL
 };
 
-struct gdtr {
-       uint16_t size;
-       uint64_t ptr;
-} __packed;
-
-#define PG_V   0x001
-#define PG_RW  0x002
-#define PG_PS  0x080
-
-#define GDT_P  0x00800000000000
-#define GDT_E  0x00080000000000
-#define GDT_S  0x00100000000000
-#define GDT_RW 0x00020000000000
-#define GDT_L  0x20000000000000
-
-typedef uint64_t p4_entry_t;
-typedef uint64_t p3_entry_t;
-typedef uint64_t p2_entry_t;
-typedef uint64_t gdt_t;
-
-static p4_entry_t *PT4;
-static p3_entry_t *PT3;
-static p3_entry_t *PT3_l, *PT3_u;
-static p2_entry_t *PT2;
-static p2_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1;
-static gdt_t *GDT;
+/*
+ * i386's pmap_pae.h doesn't provide this, so
+ * just typedef our own.
+ */
+typedef pdpt_entry_t pml4_entry_t;
 
 static void (*trampoline)(uint32_t stack, void *copy_finish, uint32_t kernend,
-    uint32_t modulep, uint64_t *pagetable, struct gdtr *gdtr, uint64_t entry);
+    uint32_t modulep, uint64_t *pagetable, void *gdtr, uint64_t entry);
 
 extern void *amd64_tramp;
 extern uint32_t amd64_tramp_size;
@@ -97,12 +80,23 @@ extern uint32_t amd64_tramp_size;
 static int
 elf64_exec(struct preloaded_file *fp)
 {
+       /*
+        * segments.h gives us a 32-bit gdtr, but
+        * we want a 64-bit one, so define our own.
+        */
+       struct {
+               uint16_t rd_limit;
+               uint64_t rd_base;
+       } __packed *gdtr;
        EFI_PHYSICAL_ADDRESS    ptr;
        EFI_ALLOCATE_TYPE       type;
        EFI_STATUS              err;
        struct file_metadata    *md;
-       struct gdtr             *gdtr;
        Elf_Ehdr                *ehdr;
+       pml4_entry_t            *PT4;
+       pdpt_entry_t            *PT3;
+       pd_entry_t              *PT2;
+       struct user_segment_descriptor *gdt;
        vm_offset_t             modulep, kernend, trampstack;
        int i;
 
@@ -123,36 +117,47 @@ elf64_exec(struct preloaded_file *fp)
                return (EFTYPE);
        ehdr = (Elf_Ehdr *)&(md->md_data);
 
-       /*
-        * Make our temporary stack 32 bytes big, which is
-        * a little more than we need.
-        */
        ptr = G(1);
        err = BS->AllocatePages(type, EfiLoaderCode,
-           EFI_SIZE_TO_PAGES(amd64_tramp_size + 32), &ptr);
+           EFI_SIZE_TO_PAGES(amd64_tramp_size), &ptr);
        if (EFI_ERROR(err)) {
                printf("Unable to allocate trampoline\n");
                return (ENOMEM);
        }
 
        trampoline = (void *)(uintptr_t)ptr;
-       trampstack = ptr + amd64_tramp_size + 32;
        bcopy(&amd64_tramp, trampoline, amd64_tramp_size);
 
+       /*
+        * Allocate enough space for the GDTR + two GDT segments +
+        * our temporary stack (28 bytes).
+        */
+#define DATASZ (sizeof(*gdtr) + \
+           sizeof(struct user_segment_descriptor) * 2 + 28)
+
        ptr = G(1);
        err = BS->AllocatePages(type, EfiLoaderData,
-           EFI_SIZE_TO_PAGES(sizeof(struct gdtr) + sizeof(uint64_t) * 2), 
&ptr);
+           EFI_SIZE_TO_PAGES(DATASZ), &ptr);
        if (EFI_ERROR(err)) {
-               printf("Unable to allocate GDT\n");
+               printf("Unable to allocate GDT and stack\n");
                BS->FreePages((uintptr_t)trampoline, 1);
                return (ENOMEM);
        }
-       GDT = (gdt_t *)(uintptr_t)ptr;
-       GDT[1] = GDT_P | GDT_E | GDT_S | GDT_RW | GDT_L; /* CS */
-       GDT[0] = 0;
-       gdtr = (struct gdtr *)&GDT[2];
-       gdtr->size = sizeof(uint64_t) * 2 - 1;
-       gdtr->ptr = (uintptr_t)GDT;
+
+       trampstack = ptr + DATASZ;
+
+#undef DATASZ
+
+       gdt = (void *)(uintptr_t)ptr;
+       gdt[0] = (struct user_segment_descriptor) { 0 };
+       gdt[1] = (struct user_segment_descriptor) {
+           .sd_p = 1, .sd_long = 1, .sd_type = SDT_MEMERC
+       };
+
+       gdtr = (void *)(uintptr_t)(ptr +
+           sizeof(struct user_segment_descriptor) * 2);
+       gdtr->rd_limit = sizeof(struct user_segment_descriptor) * 2 - 1;
+       gdtr->rd_base = (uintptr_t)gdt;
 
        if (type == AllocateMaxAddress) {
                /* Copy staging enabled */
@@ -163,10 +168,10 @@ elf64_exec(struct preloaded_file *fp)
                if (EFI_ERROR(err)) {
                        printf("Unable to allocate trampoline page table\n");
                        BS->FreePages((uintptr_t)trampoline, 1);
-                       BS->FreePages((uintptr_t)GDT, 1);
+                       BS->FreePages((uintptr_t)gdt, 1);
                        return (ENOMEM);
                }
-               PT4 = (p4_entry_t *)(uintptr_t)ptr;
+               PT4 = (pml4_entry_t *)(uintptr_t)ptr;
 
                PT3 = &PT4[512];
                PT2 = &PT3[512];
@@ -195,15 +200,18 @@ elf64_exec(struct preloaded_file *fp)
                        PT2[i] = (i * M(2)) | PG_V | PG_RW | PG_PS;
                }
        } else {
+               pdpt_entry_t    *PT3_l, *PT3_u;
+               pd_entry_t      *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, 
*PT2_u1;
+
                err = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
                    EFI_SIZE_TO_PAGES(512 * 9 * sizeof(uint64_t)), &ptr);
                if (EFI_ERROR(err)) {
                        printf("Unable to allocate trampoline page table\n");
                        BS->FreePages((uintptr_t)trampoline, 1);
-                       BS->FreePages((uintptr_t)GDT, 1);
+                       BS->FreePages((uintptr_t)gdt, 1);
                        return (ENOMEM);
                }
-               PT4 = (p4_entry_t *)(uintptr_t)ptr;
+               PT4 = (pml4_entry_t *)(uintptr_t)ptr;
 
                PT3_l = &PT4[512];
                PT3_u = &PT3_l[512];
@@ -221,7 +229,7 @@ elf64_exec(struct preloaded_file *fp)
                PT3_l[2] = (uintptr_t)PT2_l2 | PG_V | PG_RW;
                PT3_l[3] = (uintptr_t)PT2_l3 | PG_V | PG_RW;
                for (i = 0; i < 2048; i++) {
-                       PT2_l0[i] = ((p2_entry_t)i * M(2)) | PG_V | PG_RW | 
PG_PS;
+                       PT2_l0[i] = ((pd_entry_t)i * M(2)) | PG_V | PG_RW | 
PG_PS;
                }
 
                /* mapping of kernel 2G below top */
@@ -240,7 +248,7 @@ elf64_exec(struct preloaded_file *fp)
        printf(
            "staging %#llx (%scopying) tramp %p PT4 %p GDT %p\n"
            "Start @ %#llx ...\n", staging,
-           type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, GDT,
+           type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, gdt,
            ehdr->e_entry
        );
 
diff --git a/stand/i386/libi386/elf64_freebsd.c 
b/stand/i386/libi386/elf64_freebsd.c
index b1340fd1f2e2..89cc249e9d96 100644
--- a/stand/i386/libi386/elf64_freebsd.c
+++ b/stand/i386/libi386/elf64_freebsd.c
@@ -28,8 +28,11 @@
 #include <sys/param.h>
 #include <sys/exec.h>
 #include <sys/linker.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
 #include <string.h>
 #include <machine/bootinfo.h>
+#include <machine/pmap_pae.h>
 #include <machine/elf.h>
 #include <stand.h>
 
@@ -43,16 +46,15 @@ static int  elf64_obj_exec(struct preloaded_file *amp);
 struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
 struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
 
-#define PG_V   0x001
-#define PG_RW  0x002
-#define PG_PS  0x080
+/*
+ * i386's pmap_pae.h doesn't provide this, so
+ * just typedef our own.
+ */
+typedef pdpt_entry_t pml4_entry_t;
 
-typedef uint64_t p4_entry_t;
-typedef uint64_t p3_entry_t;
-typedef uint64_t p2_entry_t;
-extern p4_entry_t PT4[];
-extern p3_entry_t PT3[];
-extern p2_entry_t PT2[];
+extern pml4_entry_t    PT4[];
+extern pdpt_entry_t    PT3[];
+extern pd_entry_t      PT2[];
 
 uint32_t entry_hi;
 uint32_t entry_lo;
@@ -91,11 +93,11 @@ elf64_exec(struct preloaded_file *fp)
      */
     for (i = 0; i < 512; i++) {
        /* Each slot of the level 4 pages points to the same level 3 page */
-       PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]);
+       PT4[i] = (pml4_entry_t)VTOP((uintptr_t)&PT3[0]);
        PT4[i] |= PG_V | PG_RW;
 
        /* Each slot of the level 3 pages points to the same level 2 page */
-       PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]);
+       PT3[i] = (pdpt_entry_t)VTOP((uintptr_t)&PT2[0]);
        PT3[i] |= PG_V | PG_RW;
 
        /* The level 2 page slots are mapped with 2MB pages for 1GB. */
diff --git a/stand/userboot/userboot/elf64_freebsd.c 
b/stand/userboot/userboot/elf64_freebsd.c
index 7f817a44da88..5a63fdb4990c 100644
--- a/stand/userboot/userboot/elf64_freebsd.c
+++ b/stand/userboot/userboot/elf64_freebsd.c
@@ -31,9 +31,10 @@
 #ifdef DEBUG
 #include <machine/_inttypes.h>
 #endif
-#include <string.h>
-#include <i386/include/bootinfo.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
 #include <machine/elf.h>
+#include <machine/segments.h>
 #include <stand.h>
 
 #include "bootstrap.h"
@@ -45,35 +46,21 @@ static int  elf64_obj_exec(struct preloaded_file *amp);
 struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
 struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
 
-#define MSR_EFER        0xc0000080
-#define EFER_LME        0x00000100
-#define        EFER_LMA        0x00000400      /* Long mode active (R) */
-#define CR4_PAE         0x00000020
-#define        CR4_VMXE        (1UL << 13)
-#define CR4_PSE         0x00000010
-#define CR0_PG          0x80000000
-#define        CR0_PE          0x00000001      /* Protected mode Enable */
-#define        CR0_NE          0x00000020      /* Numeric Error enable (EX16 
vs IRQ13) */
-
-#define PG_V   0x001
-#define PG_RW  0x002
-#define PG_PS  0x080
-
-typedef uint64_t p4_entry_t;
-typedef uint64_t p3_entry_t;
-typedef uint64_t p2_entry_t;
-
 #define        GUEST_NULL_SEL          0
 #define        GUEST_CODE_SEL          1
 #define        GUEST_DATA_SEL          2
 #define        GUEST_GDTR_LIMIT        (3 * 8 - 1)
 
 static void
-setup_freebsd_gdt(uint64_t *gdtr)
+setup_freebsd_gdt(struct user_segment_descriptor *gdt)
 {
-       gdtr[GUEST_NULL_SEL] = 0;
-       gdtr[GUEST_CODE_SEL] = 0x0020980000000000;
-       gdtr[GUEST_DATA_SEL] = 0x0000900000000000;
+       gdt[GUEST_NULL_SEL] = (struct user_segment_descriptor) { 0 };
+       gdt[GUEST_CODE_SEL] = (struct user_segment_descriptor) {
+           .sd_p = 1, .sd_long = 1, .sd_type = SDT_MEME
+       };
+       gdt[GUEST_DATA_SEL] = (struct user_segment_descriptor) {
+           .sd_p = 1, .sd_type = SDT_MEMRO
+       };
 }
 
 /*
@@ -90,10 +77,10 @@ elf64_exec(struct preloaded_file *fp)
        int                     err;
        int                     i;
        uint32_t                stack[1024];
-       p4_entry_t              PT4[512];
-       p3_entry_t              PT3[512];
-       p2_entry_t              PT2[512];
-       uint64_t                gdtr[3];
+       pml4_entry_t            PT4[512];
+       pdp_entry_t             PT3[512];
+       pd_entry_t              PT2[512];
+       struct user_segment_descriptor gdt[3];
 
        if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
                return(EFTYPE);
@@ -122,11 +109,11 @@ elf64_exec(struct preloaded_file *fp)
         */
        for (i = 0; i < 512; i++) {
                /* Each slot of the level 4 pages points to the same level 3 
page */
-               PT4[i] = (p4_entry_t) 0x3000;
+               PT4[i] = (pml4_entry_t) 0x3000;
                PT4[i] |= PG_V | PG_RW;
 
                /* Each slot of the level 3 pages points to the same level 2 
page */
-               PT3[i] = (p3_entry_t) 0x4000;
+               PT3[i] = (pdp_entry_t) 0x4000;
                PT3[i] |= PG_V | PG_RW;
 
                /* The level 2 page slots are mapped with 2MB pages for 1GB. */
@@ -154,9 +141,9 @@ elf64_exec(struct preloaded_file *fp)
        CALLBACK(setcr, 3, 0x2000);
        CALLBACK(setcr, 0, CR0_PG | CR0_PE | CR0_NE);
 
-       setup_freebsd_gdt(gdtr);
-       CALLBACK(copyin, gdtr, 0x5000, sizeof(gdtr));
-        CALLBACK(setgdt, 0x5000, sizeof(gdtr));
+       setup_freebsd_gdt(gdt);
+       CALLBACK(copyin, gdt, 0x5000, sizeof(gdt));
+       CALLBACK(setgdt, 0x5000, sizeof(gdt));
 
        CALLBACK(exec, ehdr->e_entry);
 

Reply via email to