git: 5e8bd45ffb41 - main - stand/elf64_freebsd.c: use headers instead of doing things ourselves
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 05 Dec 2024 00:18:56 UTC
The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=5e8bd45ffb416f6d4e041690e3e656fd907492bf commit 5e8bd45ffb416f6d4e041690e3e656fd907492bf Author: Ahmad Khalifa <ahmadkhalifa570@gmail.com> AuthorDate: 2024-09-27 16:08:11 +0000 Commit: Warner Losh <imp@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);