stand: Initial kboot support on amd64
Get amd64 compiling. However, the current kboot supports an old way of enumerating memory and the new way needs to be incorporated as well. The powerpc folks could use either, it seems and newer powerpc platforms need some changes for kboot to work anyway. This commit includes the linker script, trampoline code to start the new kernel, Linux system calls and the necessary configuration glue needed to build the binaries. This includes a quick hack to get multiboot support, but we need to really share these defines. The multiiboot2.h is the minimum needed to build. We have multiboot information in three places now, so a refactoring is in order. This should be considered, at best, preliminary and experimental for anybody wishing to try it out. Sponsored by: Netflix Reviewed by: tsoome Differential Revision: https://reviews.freebsd.org/D35100
This commit is contained in:
parent
6c8ab086fe
commit
7df08a14e3
@ -301,8 +301,8 @@ BROKEN_OPTIONS+=EFI
|
|||||||
.if ${__T:Mpowerpc*} == ""
|
.if ${__T:Mpowerpc*} == ""
|
||||||
BROKEN_OPTIONS+=LOADER_OFW
|
BROKEN_OPTIONS+=LOADER_OFW
|
||||||
.endif
|
.endif
|
||||||
# KBOOT is only for powerpc64 (powerpc64le broken)
|
# KBOOT is only for powerpc64 (powerpc64le broken) and kinda for amd64
|
||||||
.if ${__T} != "powerpc64"
|
.if ${__T} != "powerpc64" && ${__T} != "amd64"
|
||||||
BROKEN_OPTIONS+=LOADER_KBOOT
|
BROKEN_OPTIONS+=LOADER_KBOOT
|
||||||
.endif
|
.endif
|
||||||
# UBOOT is only for arm, and big-endian powerpc
|
# UBOOT is only for arm, and big-endian powerpc
|
||||||
|
8
stand/kboot/arch/amd64/Makefile.inc
Normal file
8
stand/kboot/arch/amd64/Makefile.inc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
SRCS+= conf.c host_syscall.S amd64_tramp.S elf64_freebsd.c
|
||||||
|
|
||||||
|
CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include
|
||||||
|
# load address. set in linker script
|
||||||
|
RELOC?= 0x0
|
||||||
|
CFLAGS+= -DRELOC=${RELOC}
|
||||||
|
|
||||||
|
LDFLAGS= -nostdlib -static -T ${.CURDIR}/arch/${MACHINE_ARCH}/ldscript.amd64
|
76
stand/kboot/arch/amd64/amd64_tramp.S
Normal file
76
stand/kboot/arch/amd64/amd64_tramp.S
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2013 The FreeBSD Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software was developed by Benno Rice under sponsorship from
|
||||||
|
* the FreeBSD Foundation.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <machine/asmacros.h>
|
||||||
|
|
||||||
|
#define ASM_FILE
|
||||||
|
#include "multiboot2.h"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl amd64_tramp
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void amd64_tramp(uint64_t stack, void *copy_finish, uint64_t kernend,
|
||||||
|
* uint64_t modulep, uint64_t pagetable, uint64_t entry)
|
||||||
|
*/
|
||||||
|
amd64_tramp:
|
||||||
|
cli /* Make sure we don't get interrupted. */
|
||||||
|
movq %rdi,%rsp /* Switch to our temporary stack. */
|
||||||
|
|
||||||
|
movq %rdx,%r12 /* Stash the kernel values for later. */
|
||||||
|
movq %rcx,%r13
|
||||||
|
movq %r8,%r14
|
||||||
|
movq %r9,%r15
|
||||||
|
|
||||||
|
callq *%rsi /* Call copy_finish so we're all ready to go. */
|
||||||
|
|
||||||
|
pushq %r12 /* Push kernend. */
|
||||||
|
salq $32,%r13 /* Shift modulep and push it. */
|
||||||
|
pushq %r13
|
||||||
|
pushq %r15 /* Push the entry address. */
|
||||||
|
movq %r14,%cr3 /* Switch page tables. */
|
||||||
|
ret /* "Return" to kernel entry. */
|
||||||
|
|
||||||
|
ALIGN_TEXT
|
||||||
|
amd64_tramp_end:
|
||||||
|
|
||||||
|
/* void multiboot2_exec(uint64_t entry, uint64_t multiboot_info, uint64_t stack) */
|
||||||
|
.globl multiboot2_exec
|
||||||
|
multiboot2_exec:
|
||||||
|
movq %rdx,%rsp
|
||||||
|
pushq %rdi
|
||||||
|
movq %rsi,%rbx
|
||||||
|
movq $MULTIBOOT2_BOOTLOADER_MAGIC,%rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.data
|
||||||
|
.globl amd64_tramp_size
|
||||||
|
amd64_tramp_size:
|
||||||
|
.long amd64_tramp_end-amd64_tramp
|
104
stand/kboot/arch/amd64/conf.c
Normal file
104
stand/kboot/arch/amd64/conf.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (C) 1999 Michael Smith <msmith@freebsd.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <stand.h>
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
|
#if defined(LOADER_NET_SUPPORT)
|
||||||
|
#include "dev_net.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern struct devsw hostdisk;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We could use linker sets for some or all of these, but
|
||||||
|
* then we would have to control what ended up linked into
|
||||||
|
* the bootstrap. So it's easier to conditionalise things
|
||||||
|
* here.
|
||||||
|
*
|
||||||
|
* XXX rename these arrays to be consistent and less namespace-hostile
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported for libsa */
|
||||||
|
struct devsw *devsw[] = {
|
||||||
|
#if defined(LOADER_DISK_SUPPORT) || defined(LOADER_CD9660_SUPPORT)
|
||||||
|
&hostdisk,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_NET_SUPPORT)
|
||||||
|
&netdev,
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_ops *file_system[] = {
|
||||||
|
#if defined(LOADER_UFS_SUPPORT)
|
||||||
|
&ufs_fsops,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_CD9660_SUPPORT)
|
||||||
|
&cd9660_fsops,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_EXT2FS_SUPPORT)
|
||||||
|
&ext2fs_fsops,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_NFS_SUPPORT)
|
||||||
|
&nfs_fsops,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_TFTP_SUPPORT)
|
||||||
|
&tftp_fsops,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_GZIP_SUPPORT)
|
||||||
|
&gzipfs_fsops,
|
||||||
|
#endif
|
||||||
|
#if defined(LOADER_BZIP2_SUPPORT)
|
||||||
|
&bzipfs_fsops,
|
||||||
|
#endif
|
||||||
|
&dosfs_fsops,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct netif_driver kbootnet;
|
||||||
|
|
||||||
|
struct netif_driver *netif_drivers[] = {
|
||||||
|
#if 0 /* XXX */
|
||||||
|
#if defined(LOADER_NET_SUPPORT)
|
||||||
|
&kbootnet,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Consoles
|
||||||
|
*/
|
||||||
|
extern struct console hostconsole;
|
||||||
|
|
||||||
|
struct console *consoles[] = {
|
||||||
|
&hostconsole,
|
||||||
|
NULL
|
||||||
|
};
|
345
stand/kboot/arch/amd64/elf64_freebsd.c
Normal file
345
stand/kboot/arch/amd64/elf64_freebsd.c
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
|
||||||
|
* Copyright (c) 2014 The FreeBSD Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#define __ELF_WORD_SIZE 64
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/exec.h>
|
||||||
|
#include <sys/linker.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <machine/elf.h>
|
||||||
|
#include <stand.h>
|
||||||
|
#include <vm/vm.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
|
#include "platform/acfreebsd.h"
|
||||||
|
#include "acconfig.h"
|
||||||
|
#define ACPI_SYSTEM_XFACE
|
||||||
|
#include "actypes.h"
|
||||||
|
#include "actbl.h"
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
#include "loader_efi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
|
||||||
|
static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
#define LOADER_PAGE_SIZE EFI_PAGE_SIZE
|
||||||
|
#else
|
||||||
|
#define LOADER_PAGE_SIZE 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||||
|
bool exit_bs);
|
||||||
|
|
||||||
|
static int elf64_exec(struct preloaded_file *amp);
|
||||||
|
static int elf64_obj_exec(struct preloaded_file *amp);
|
||||||
|
|
||||||
|
static struct file_format amd64_elf = {
|
||||||
|
.l_load = elf64_loadfile,
|
||||||
|
.l_exec = elf64_exec,
|
||||||
|
};
|
||||||
|
static struct file_format amd64_elf_obj = {
|
||||||
|
.l_load = elf64_obj_loadfile,
|
||||||
|
.l_exec = elf64_obj_exec,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
extern struct file_format multiboot2;
|
||||||
|
extern struct file_format multiboot2_obj;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct file_format *file_formats[] = {
|
||||||
|
#if 0
|
||||||
|
&multiboot2,
|
||||||
|
&multiboot2_obj,
|
||||||
|
#endif
|
||||||
|
&amd64_elf,
|
||||||
|
&amd64_elf_obj,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
static pml4_entry_t *PT4;
|
||||||
|
static pdp_entry_t *PT3;
|
||||||
|
static pdp_entry_t *PT3_l, *PT3_u;
|
||||||
|
static pd_entry_t *PT2;
|
||||||
|
static pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1;
|
||||||
|
|
||||||
|
extern EFI_PHYSICAL_ADDRESS staging;
|
||||||
|
|
||||||
|
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
|
||||||
|
uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uintptr_t amd64_tramp;
|
||||||
|
extern uint32_t amd64_tramp_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is an ELF kernel and one or more ELF modules loaded.
|
||||||
|
* We wish to start executing the kernel image, so make such
|
||||||
|
* preparations as are required, and do so.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
elf64_exec(struct preloaded_file *fp)
|
||||||
|
{
|
||||||
|
#ifdef EFI
|
||||||
|
struct file_metadata *md;
|
||||||
|
Elf_Ehdr *ehdr;
|
||||||
|
vm_offset_t modulep, kernend, trampcode, trampstack;
|
||||||
|
int err, i;
|
||||||
|
ACPI_TABLE_RSDP *rsdp;
|
||||||
|
char buf[24];
|
||||||
|
int revision;
|
||||||
|
bool copy_auto;
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
copy_auto = copy_staging == COPY_STAGING_AUTO;
|
||||||
|
if (copy_auto)
|
||||||
|
copy_staging = fp->f_kernphys_relocatable ?
|
||||||
|
COPY_STAGING_DISABLE : COPY_STAGING_ENABLE;
|
||||||
|
#else
|
||||||
|
copy_auto = COPY_STAGING_DISABLE; /* XXX */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report the RSDP to the kernel. While this can be found with
|
||||||
|
* a BIOS boot, the RSDP may be elsewhere when booted from UEFI.
|
||||||
|
* The old code used the 'hints' method to communite this to
|
||||||
|
* the kernel. However, while convenient, the 'hints' method
|
||||||
|
* is fragile and does not work when static hints are compiled
|
||||||
|
* into the kernel. Instead, move to setting different tunables
|
||||||
|
* that start with acpi. The old 'hints' can be removed before
|
||||||
|
* we branch for FreeBSD 12.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
rsdp = efi_get_table(&acpi20_guid);
|
||||||
|
if (rsdp == NULL) {
|
||||||
|
rsdp = efi_get_table(&acpi_guid);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
rsdp = NULL;
|
||||||
|
#warning "write me"
|
||||||
|
#endif
|
||||||
|
if (rsdp != NULL) {
|
||||||
|
sprintf(buf, "0x%016llx", (unsigned long long)rsdp);
|
||||||
|
setenv("hint.acpi.0.rsdp", buf, 1);
|
||||||
|
setenv("acpi.rsdp", buf, 1);
|
||||||
|
revision = rsdp->Revision;
|
||||||
|
if (revision == 0)
|
||||||
|
revision = 1;
|
||||||
|
sprintf(buf, "%d", revision);
|
||||||
|
setenv("hint.acpi.0.revision", buf, 1);
|
||||||
|
setenv("acpi.revision", buf, 1);
|
||||||
|
strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
|
||||||
|
buf[sizeof(rsdp->OemId)] = '\0';
|
||||||
|
setenv("hint.acpi.0.oem", buf, 1);
|
||||||
|
setenv("acpi.oem", buf, 1);
|
||||||
|
sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress);
|
||||||
|
setenv("hint.acpi.0.rsdt", buf, 1);
|
||||||
|
setenv("acpi.rsdt", buf, 1);
|
||||||
|
if (revision >= 2) {
|
||||||
|
/* XXX extended checksum? */
|
||||||
|
sprintf(buf, "0x%016llx",
|
||||||
|
(unsigned long long)rsdp->XsdtPhysicalAddress);
|
||||||
|
setenv("hint.acpi.0.xsdt", buf, 1);
|
||||||
|
setenv("acpi.xsdt", buf, 1);
|
||||||
|
sprintf(buf, "%d", rsdp->Length);
|
||||||
|
setenv("hint.acpi.0.xsdt_length", buf, 1);
|
||||||
|
setenv("acpi.xsdt_length", buf, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
|
||||||
|
return (EFTYPE);
|
||||||
|
ehdr = (Elf_Ehdr *)&(md->md_data);
|
||||||
|
|
||||||
|
trampcode = copy_staging == COPY_STAGING_ENABLE ?
|
||||||
|
(vm_offset_t)0x0000000040000000 /* 1G */ :
|
||||||
|
(vm_offset_t)0x0000000100000000; /* 4G */;
|
||||||
|
#ifdef EFI
|
||||||
|
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
|
||||||
|
(EFI_PHYSICAL_ADDRESS *)&trampcode);
|
||||||
|
if (EFI_ERROR(err)) {
|
||||||
|
printf("Unable to allocate trampoline\n");
|
||||||
|
if (copy_auto)
|
||||||
|
copy_staging = COPY_STAGING_AUTO;
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#warning "Write me"
|
||||||
|
#endif
|
||||||
|
bzero((void *)trampcode, LOADER_PAGE_SIZE);
|
||||||
|
trampstack = trampcode + LOADER_PAGE_SIZE - 8;
|
||||||
|
bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size);
|
||||||
|
trampoline = (void *)trampcode;
|
||||||
|
|
||||||
|
if (copy_staging == COPY_STAGING_ENABLE) {
|
||||||
|
PT4 = (pml4_entry_t *)0x0000000040000000;
|
||||||
|
#ifdef EFI
|
||||||
|
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
|
||||||
|
(EFI_PHYSICAL_ADDRESS *)&PT4);
|
||||||
|
if (EFI_ERROR(err)) {
|
||||||
|
printf("Unable to allocate trampoline page table\n");
|
||||||
|
BS->FreePages(trampcode, 1);
|
||||||
|
if (copy_auto)
|
||||||
|
copy_staging = COPY_STAGING_AUTO;
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#warning "Write me"
|
||||||
|
#endif
|
||||||
|
bzero(PT4, 3 * LOADER_PAGE_SIZE);
|
||||||
|
PT3 = &PT4[512];
|
||||||
|
PT2 = &PT3[512];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is kinda brutal, but every single 1GB VM
|
||||||
|
* memory segment points to the same first 1GB of
|
||||||
|
* physical memory. But it is more than adequate.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < NPTEPG; i++) {
|
||||||
|
/*
|
||||||
|
* Each slot of the L4 pages points to the
|
||||||
|
* same L3 page.
|
||||||
|
*/
|
||||||
|
PT4[i] = (pml4_entry_t)PT3;
|
||||||
|
PT4[i] |= PG_V | PG_RW;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each slot of the L3 pages points to the
|
||||||
|
* same L2 page.
|
||||||
|
*/
|
||||||
|
PT3[i] = (pdp_entry_t)PT2;
|
||||||
|
PT3[i] |= PG_V | PG_RW;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The L2 page slots are mapped with 2MB pages for 1GB.
|
||||||
|
*/
|
||||||
|
PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024);
|
||||||
|
PT2[i] |= PG_V | PG_RW | PG_PS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */
|
||||||
|
#ifdef EFI
|
||||||
|
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9,
|
||||||
|
(EFI_PHYSICAL_ADDRESS *)&PT4);
|
||||||
|
if (EFI_ERROR(err)) {
|
||||||
|
printf("Unable to allocate trampoline page table\n");
|
||||||
|
BS->FreePages(trampcode, 9);
|
||||||
|
if (copy_auto)
|
||||||
|
copy_staging = COPY_STAGING_AUTO;
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#warning "Write me"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bzero(PT4, 9 * LOADER_PAGE_SIZE);
|
||||||
|
|
||||||
|
PT3_l = &PT4[NPML4EPG * 1];
|
||||||
|
PT3_u = &PT4[NPML4EPG * 2];
|
||||||
|
PT2_l0 = &PT4[NPML4EPG * 3];
|
||||||
|
PT2_l1 = &PT4[NPML4EPG * 4];
|
||||||
|
PT2_l2 = &PT4[NPML4EPG * 5];
|
||||||
|
PT2_l3 = &PT4[NPML4EPG * 6];
|
||||||
|
PT2_u0 = &PT4[NPML4EPG * 7];
|
||||||
|
PT2_u1 = &PT4[NPML4EPG * 8];
|
||||||
|
|
||||||
|
/* 1:1 mapping of lower 4G */
|
||||||
|
PT4[0] = (pml4_entry_t)PT3_l | PG_V | PG_RW;
|
||||||
|
PT3_l[0] = (pdp_entry_t)PT2_l0 | PG_V | PG_RW;
|
||||||
|
PT3_l[1] = (pdp_entry_t)PT2_l1 | PG_V | PG_RW;
|
||||||
|
PT3_l[2] = (pdp_entry_t)PT2_l2 | PG_V | PG_RW;
|
||||||
|
PT3_l[3] = (pdp_entry_t)PT2_l3 | PG_V | PG_RW;
|
||||||
|
for (i = 0; i < 4 * NPDEPG; i++) {
|
||||||
|
PT2_l0[i] = ((pd_entry_t)i << PDRSHIFT) | PG_V |
|
||||||
|
PG_RW | PG_PS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mapping of kernel 2G below top */
|
||||||
|
PT4[NPML4EPG - 1] = (pml4_entry_t)PT3_u | PG_V | PG_RW;
|
||||||
|
PT3_u[NPDPEPG - 2] = (pdp_entry_t)PT2_u0 | PG_V | PG_RW;
|
||||||
|
PT3_u[NPDPEPG - 1] = (pdp_entry_t)PT2_u1 | PG_V | PG_RW;
|
||||||
|
/* compat mapping of phys @0 */
|
||||||
|
PT2_u0[0] = PG_PS | PG_V | PG_RW;
|
||||||
|
/* this maps past staging area */
|
||||||
|
for (i = 1; i < 2 * NPDEPG; i++) {
|
||||||
|
PT2_u0[i] = ((pd_entry_t)staging +
|
||||||
|
((pd_entry_t)i - 1) * NBPDR) |
|
||||||
|
PG_V | PG_RW | PG_PS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("staging %#lx (%scopying) tramp %p PT4 %p\n",
|
||||||
|
staging, copy_staging == COPY_STAGING_ENABLE ? "" : "not ",
|
||||||
|
trampoline, PT4);
|
||||||
|
printf("Start @ 0x%lx ...\n", ehdr->e_entry);
|
||||||
|
|
||||||
|
#ifdef EFI
|
||||||
|
efi_time_fini();
|
||||||
|
#endif
|
||||||
|
err = bi_load(fp->f_args, &modulep, &kernend, true);
|
||||||
|
if (err != 0) {
|
||||||
|
#ifdef EFI
|
||||||
|
efi_time_init();
|
||||||
|
#endif
|
||||||
|
if (copy_auto)
|
||||||
|
copy_staging = COPY_STAGING_AUTO;
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_cleanup();
|
||||||
|
|
||||||
|
trampoline(trampstack, copy_staging == COPY_STAGING_ENABLE ?
|
||||||
|
efi_copy_finish : efi_copy_finish_nop, kernend, modulep,
|
||||||
|
PT4, ehdr->e_entry);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
panic("exec returned");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
elf64_obj_exec(struct preloaded_file *fp)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (EFTYPE);
|
||||||
|
}
|
29
stand/kboot/arch/amd64/host_syscall.S
Normal file
29
stand/kboot/arch/amd64/host_syscall.S
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emulate the Linux system call interface. The system call number is set in
|
||||||
|
* %rax, and %rdi, %rsi, %rdx, %r10, %r8, %r9 have the 6 system call
|
||||||
|
* arguments. errno is returned as a negative value, but we use it more as a
|
||||||
|
* flag something went wrong rather than using its value.
|
||||||
|
*
|
||||||
|
* Note: For system calls, we use %r10 instead of %rcx for the 4th argument.
|
||||||
|
* See section A.2.1 for the Linux calling conventions of the ABI spec
|
||||||
|
* https://web.archive.org/web/20160801075146/http://www.x86-64.org/documentation/abi.pdf
|
||||||
|
* In addition to the below, %r11 and %rcx are destroyed, negative
|
||||||
|
* values are ERRNO for %rax between -1 and -4095 otherwise the system
|
||||||
|
* call is successful. Unlike other Unix systems, carry isn't used to
|
||||||
|
* signal an error in the system call. We expose the raw system call
|
||||||
|
* result, rather than do the POSIX converion to -1 and setting errno.
|
||||||
|
*/
|
||||||
|
ENTRY(host_syscall)
|
||||||
|
movq %rdi, %rax /* SYS_ number in %rax */
|
||||||
|
movq %rsi, %rdi /* arg2 -> 1 */
|
||||||
|
movq %rdx, %rsi /* arg3 -> 2 */
|
||||||
|
movq %rcx, %rdx /* arg4 -> 3 */
|
||||||
|
movq %r8, %r10 /* arg5 -> 4 */
|
||||||
|
movq %r9, %r8 /* arg6 -> 5 */
|
||||||
|
movq 8(%rsp),%r9 /* arg7 -> 6 from stack. */
|
||||||
|
syscall
|
||||||
|
ret
|
||||||
|
/* Note: We're exposing the raw return value to the caller */
|
||||||
|
END(host_syscall)
|
72
stand/kboot/arch/amd64/ldscript.amd64
Normal file
72
stand/kboot/arch/amd64/ldscript.amd64
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* $FreeBSD$ */
|
||||||
|
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||||
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
. = 0x401000;
|
||||||
|
ImageBase = .;
|
||||||
|
.hash : { *(.hash) } /* this MUST come first! */
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.eh_frame :
|
||||||
|
{
|
||||||
|
*(.eh_frame)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.text : {
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.plt)
|
||||||
|
} =0xCCCCCCCC
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.data : {
|
||||||
|
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||||
|
*(.rodata1)
|
||||||
|
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||||
|
*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
|
||||||
|
*(.opd)
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
*(.data1)
|
||||||
|
*(.plabel)
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
set_Xcommand_set : {
|
||||||
|
__start_set_Xcommand_set = .;
|
||||||
|
*(set_Xcommand_set)
|
||||||
|
__stop_set_Xcommand_set = .;
|
||||||
|
}
|
||||||
|
set_Xficl_compile_set : {
|
||||||
|
__start_set_Xficl_compile_set = .;
|
||||||
|
*(set_Xficl_compile_set)
|
||||||
|
__stop_set_Xficl_compile_set = .;
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__gp = .;
|
||||||
|
.sdata : {
|
||||||
|
*(.got.plt .got)
|
||||||
|
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||||
|
*(dynsbss)
|
||||||
|
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||||
|
*(.scommon)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.rela.dyn : {
|
||||||
|
*(.rela.data*)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.stab)
|
||||||
|
*(.relaset_*)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.reloc : { *(.reloc) }
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
}
|
1
stand/kboot/arch/amd64/multiboot2.h
Normal file
1
stand/kboot/arch/amd64/multiboot2.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
15
stand/kboot/arch/amd64/syscall_nr.h
Normal file
15
stand/kboot/arch/amd64/syscall_nr.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#define SYS_read 0
|
||||||
|
#define SYS_write 1
|
||||||
|
#define SYS_open 2
|
||||||
|
#define SYS_close 3
|
||||||
|
#define SYS_gettimeofday 96
|
||||||
|
#define SYS_reboot 169
|
||||||
|
#define SYS_mmap 9
|
||||||
|
#define SYS_uname 63
|
||||||
|
#define SYS_lseek 8
|
||||||
|
#define SYS_getdents 78
|
||||||
|
#define SYS_select 23
|
||||||
|
#define __NR_kexec_load 246
|
||||||
|
|
||||||
|
#define KEXEC_ARCH_X86_64 62
|
||||||
|
#define KEXEC_ARCH KEXEC_ARCH_X86_64
|
Loading…
Reference in New Issue
Block a user