Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Jul 2022 14:41:45 -0700
From:      Ravi Pokala <rpokala@freebsd.org>
To:        Warner Losh <imp@FreeBSD.org>, <src-committers@FreeBSD.org>, <dev-commits-src-all@FreeBSD.org>, <dev-commits-src-main@FreeBSD.org>
Subject:   Re: 75cbdbc9832e - main - kboot: aarch64 support
Message-ID:  <7CE3657B-5DBF-43D3-BBB2-1391764A96CB@panasas.com>
In-Reply-To: <202207282137.26SLbikk001662@gitrepo.freebsd.org>
References:  <202207282137.26SLbikk001662@gitrepo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
> exec.c tweaked slightly

Relative to what?

-Ravi (rpokala@)

=EF=BB=BF-----Original Message-----
From: <owner-src-committers@freebsd.org> on behalf of Warner Losh <imp@Free=
BSD.org>
Date: 2022-07-28, Thursday at 14:37
To: <src-committers@FreeBSD.org>, <dev-commits-src-all@FreeBSD.org>, <dev-c=
ommits-src-main@FreeBSD.org>
Subject: git: 75cbdbc9832e - main - kboot: aarch64 support

    The branch main has been updated by imp:

    URL: https://cgit.FreeBSD.org/src/commit/?id=3D75cbdbc9832e72a59bdcb1c307=
a7a4ea77e29fce

    commit 75cbdbc9832e72a59bdcb1c307a7a4ea77e29fce
    Author:     Warner Losh <imp@FreeBSD.org>
    AuthorDate: 2022-07-11 23:49:11 +0000
    Commit:     Warner Losh <imp@FreeBSD.org>
    CommitDate: 2022-07-28 21:35:42 +0000

        kboot: aarch64 support

        Add support for aarch64. exec.c and ldscript are copied from the EF=
I
        version with #ifdefs for the differences. Once complete, I'll refac=
tor
        them. host_syscall.S implements a generic system call. tramp.S is a
        first attempt to create a tramoline that we can use to jump to the
        aarch64 kernel. Add aarch64-specific startup and stat files as well=
.
        exec.c tweaked slightly to avoid bringing in bi_load(), which will =
come
        in later. Includes tweaks to stat due to name differences between n=
ames
        on different Linux architectures.

        Sponsored by:           Netflix
    ---
     stand/kboot/arch/aarch64/Makefile.inc     |  12 ++
     stand/kboot/arch/aarch64/exec.c           | 188 ++++++++++++++++++++++=
++++++++
     stand/kboot/arch/aarch64/host_syscall.S   |  18 +++
     stand/kboot/arch/aarch64/ldscript.aarch64 |  72 ++++++++++++
     stand/kboot/arch/aarch64/load_addr.c      |   0
     stand/kboot/arch/aarch64/start_arch.h     |  36 ++++++
     stand/kboot/arch/aarch64/stat_arch.h      |  29 +++++
     stand/kboot/arch/aarch64/syscall_nr.h     |  20 ++++
     stand/kboot/arch/aarch64/tramp.S          |  67 +++++++++++
     stand/kboot/host_syscalls.c               |   5 +
     10 files changed, 447 insertions(+)

    diff --git a/stand/kboot/arch/aarch64/Makefile.inc b/stand/kboot/arch/a=
arch64/Makefile.inc
    new file mode 100644
    index 000000000000..5573d264ec4e
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/Makefile.inc
    @@ -0,0 +1,12 @@
    +SRCS+=3D		host_syscall.S tramp.S exec.c load_addr.c
    +
    +.PATH:	${BOOTSRC}/arm64/libarm64
    +CFLAGS+=3D-I${BOOTSRC}/arm64/libarm64
    +SRCS+=3D	cache.c
    +
    +CFLAGS+=3D	-I${SYSDIR}/contrib/dev/acpica/include
    +# load address. set in linker script
    +RELOC?=3D		0x0
    +CFLAGS+=3D	-DRELOC=3D${RELOC}
    +
    +LDFLAGS=3D	-nostdlib -static -T ${.CURDIR}/arch/${MACHINE_ARCH}/ldscript=
.${MACHINE_ARCH}
    diff --git a/stand/kboot/arch/aarch64/exec.c b/stand/kboot/arch/aarch64=
/exec.c
    new file mode 100644
    index 000000000000..56a206c0f09f
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/exec.c
    @@ -0,0 +1,188 @@
    +/*-
    + * Copyright (c) 2006 Marcel Moolenaar
    + * 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 copyrigh=
t
    + *    notice, this list of conditions and the following disclaimer in =
the
    + *    documentation and/or other materials provided with the distribut=
ion.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS O=
R
    + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARR=
ANTIES
    + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAI=
MED.
    + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING=
, BUT
    + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS O=
F USE,
    + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON A=
NY
    + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE U=
SE OF
    + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    + */
    +
    +#include <sys/cdefs.h>
    +__FBSDID("$FreeBSD$");
    +
    +#include <stand.h>
    +#include <string.h>
    +
    +#include <sys/param.h>
    +#include <sys/linker.h>
    +#include <machine/elf.h>
    +
    +#include <bootstrap.h>
    +
    +#ifdef EFI
    +#include <efi.h>
    +#include <efilib.h>
    +
    +#include "loader_efi.h"
    +
    +#endif
    +
    +#include "bootstrap.h"
    +
    +#include "platform/acfreebsd.h"
    +#include "acconfig.h"
    +#define ACPI_SYSTEM_XFACE
    +#include "actypes.h"
    +#include "actbl.h"
    +
    +#include "cache.h"
    +
    +#ifdef EFI
    +static EFI_GUID acpi_guid =3D ACPI_TABLE_GUID;
    +static EFI_GUID acpi20_guid =3D ACPI_20_TABLE_GUID;
    +#endif
    +
    +static int elf64_exec(struct preloaded_file *amp);
    +static int elf64_obj_exec(struct preloaded_file *amp);
    +
    +/* Stub out temporarily */
    +static int
    +bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
    +    bool exit_bs)
    +{
    +	return EINVAL;
    +}
    +
    +static struct file_format arm64_elf =3D {
    +	elf64_loadfile,
    +	elf64_exec
    +};
    +
    +struct file_format *file_formats[] =3D {
    +	&arm64_elf,
    +	NULL
    +};
    +
    +static int
    +elf64_exec(struct preloaded_file *fp)
    +{
    +	vm_offset_t modulep, kernendp;
    +	vm_offset_t clean_addr;
    +	size_t clean_size;
    +	struct file_metadata *md;
    +	Elf_Ehdr *ehdr;
    +	void (*entry)(vm_offset_t);
    +	int err;
    +#ifdef EFI
    +	ACPI_TABLE_RSDP *rsdp;
    +	char buf[24];
    +	int revision;
    +#endif
    +	/*
    +	 * Report the RSDP to the kernel. The old code used the 'hints' metho=
d
    +	 * 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 tunab=
les
    +	 * that start with acpi. The old 'hints' can be removed before we bra=
nch
    +	 * for FreeBSD 15.
    +	 */
    +#ifdef EFI
    +	rsdp =3D efi_get_table(&acpi20_guid);
    +	if (rsdp =3D=3D NULL) {
    +		rsdp =3D efi_get_table(&acpi_guid);
    +	}
    +	if (rsdp !=3D NULL) {
    +		sprintf(buf, "0x%016llx", (unsigned long long)rsdp);
    +		setenv("hint.acpi.0.rsdp", buf, 1);
    +		setenv("acpi.rsdp", buf, 1);
    +		revision =3D rsdp->Revision;
    +		if (revision =3D=3D 0)
    +			revision =3D 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)] =3D '\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 >=3D 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);
    +		}
    +	}
    +#else
    +#endif
    +
    +	if ((md =3D file_findmetadata(fp, MODINFOMD_ELFHDR)) =3D=3D NULL)
    +        	return(EFTYPE);
    +
    +	ehdr =3D (Elf_Ehdr *)&(md->md_data);
    +#ifdef EFI
    +	entry =3D efi_translate(ehdr->e_entry);
    +
    +	efi_time_fini();
    +#else
    +	entry =3D (void *)ehdr->e_entry;
    +#endif
    +	err =3D bi_load(fp->f_args, &modulep, &kernendp, true);
    +	if (err !=3D 0) {
    +#ifdef EFI
    +		efi_time_init();
    +#endif
    +		return (err);
    +	}
    +
    +	dev_cleanup();
    +
    +	/* Clean D-cache under kernel area and invalidate whole I-cache */
    +#ifdef EFI
    +	clean_addr =3D (vm_offset_t)efi_translate(fp->f_addr);
    +	clean_size =3D (vm_offset_t)efi_translate(kernendp) - clean_addr;
    +#else
    +	clean_addr =3D (vm_offset_t)fp->f_addr;
    +	clean_size =3D (vm_offset_t)kernendp - clean_addr;
    +#endif
    +
    +	cpu_flush_dcache((void *)clean_addr, clean_size);
    +	cpu_inval_icache();
    +
    +	(*entry)(modulep);
    +
    +	panic("exec returned");
    +}
    +
    +static int
    +elf64_obj_exec(struct preloaded_file *fp)
    +{
    +
    +	printf("%s called for preloaded file %p (=3D%s):\n", __func__, fp,
    +	    fp->f_name);
    +	return (ENOSYS);
    +}
    +
    diff --git a/stand/kboot/arch/aarch64/host_syscall.S b/stand/kboot/arch=
/aarch64/host_syscall.S
    new file mode 100644
    index 000000000000..db3ecf0f885d
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/host_syscall.S
    @@ -0,0 +1,18 @@
    +#include <machine/asm.h>
    +
    +/*
    + * Emulate the Linux system call interface. System call number in x8.
    + * Args in x0, x1, x2, x3, x4 and x5. Return in x0.
    + */
    +ENTRY(host_syscall)
    +	mov	x8, x0
    +	mov	x0, x1
    +	mov	x1, x2
    +	mov	x2, x3
    +	mov	x3, x4
    +	mov	x4, x5
    +	mov	x5, x6
    +	svc	0
    +	ret
    +/* Note: We're exposing the raw return value to the caller */
    +END(host_syscall)
    diff --git a/stand/kboot/arch/aarch64/ldscript.aarch64 b/stand/kboot/ar=
ch/aarch64/ldscript.aarch64
    new file mode 100644
    index 000000000000..d7107fe8c18a
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/ldscript.aarch64
    @@ -0,0 +1,72 @@
    +/* $FreeBSD$ */
    +OUTPUT_FORMAT("elf64-aarch64", "elf64-aarch64", "elf64-aarch64")
    +OUTPUT_ARCH(aarch64)
    +ENTRY(_start)
    +SECTIONS
    +{
    +  /* Read-only sections, merged into text segment: */
    +  . =3D 0x401000;
    +  ImageBase =3D .;
    +  .hash : { *(.hash) }  /* this MUST come first! */
    +  . =3D ALIGN(4096);
    +  .eh_frame :
    +  {
    +    *(.eh_frame)
    +  }
    +  . =3D ALIGN(4096);
    +  .text		: {
    +    *(.text .stub .text.* .gnu.linkonce.t.*)
    +    /* .gnu.warning sections are handled specially by elf32.em. */
    +    *(.gnu.warning)
    +    *(.plt)
    +  } =3D0xCCCCCCCC
    +  . =3D 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)
    +  }
    +  . =3D ALIGN(4096);
    +  set_Xcommand_set	: {
    +    __start_set_Xcommand_set =3D .;
    +    *(set_Xcommand_set)
    +    __stop_set_Xcommand_set =3D .;
    +  }
    +  set_Xficl_compile_set	: {
    +    __start_set_Xficl_compile_set =3D .;
    +    *(set_Xficl_compile_set)
    +    __stop_set_Xficl_compile_set =3D .;
    +  }
    +  . =3D ALIGN(4096);
    +  __gp =3D .;
    +  .sdata	: {
    +    *(.got.plt .got)
    +    *(.sdata .sdata.* .gnu.linkonce.s.*)
    +    *(dynsbss)
    +    *(.sbss .sbss.* .gnu.linkonce.sb.*)
    +    *(.scommon)
    +  }
    +  . =3D ALIGN(4096);
    +  .dynamic	: { *(.dynamic) }
    +  . =3D ALIGN(4096);
    +  .rela.dyn	: {
    +    *(.rela.data*)
    +    *(.rela.got)
    +    *(.rela.stab)
    +    *(.relaset_*)
    +  }
    +  . =3D ALIGN(4096);
    +  .reloc	: { *(.reloc) }
    +  . =3D ALIGN(4096);
    +  .dynsym	: { *(.dynsym) }
    +  . =3D ALIGN(4096);
    +  .dynstr	: { *(.dynstr) }
    +}
    diff --git a/stand/kboot/arch/aarch64/load_addr.c b/stand/kboot/arch/aa=
rch64/load_addr.c
    new file mode 100644
    index 000000000000..e69de29bb2d1
    diff --git a/stand/kboot/arch/aarch64/start_arch.h b/stand/kboot/arch/a=
arch64/start_arch.h
    new file mode 100644
    index 000000000000..467ba054c9f0
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/start_arch.h
    @@ -0,0 +1,36 @@
    +/*
    + * Copyright (c) 2022, Netflix, Inc.
    + *
    + * SPDX-License-Identifier: BSD-2-Clause
    + */
    +
    +/*
    + * Provides a _start routine that calls a _start_c routine that takes =
a pointer
    + * to the stack as documented in crt1.c. We skip the pointer to _DYNAM=
IC since
    + * we don't support dynamic libraries, at all. And while _start_c is o=
ur own
    + * thing and doesn't have a second arg, we comport to the calling conv=
entions
    + * that glibc and musl have by passing x1 as 0 for the dynamic pointer=
. We
    + * likely could call main directly with only a few more lines of code,=
 but this
    + * is simple enough and concentrates all the expressable in C stuff th=
ere.  We
    + * also generate eh_frames should we need to debug things (it doesn't =
change the
    + * genreated code, but leaves enough breadcrumbs to keep gdb happy)
    + */
    +
    +__asm__(
    +".text\n"		/* ENTRY(_start) -- can't expand and stringify, so by hand =
*/
    +".align 2\n"
    +".global _start\n"
    +".type _start, #function\n"
    +"_start:\n"
    +".cfi_startproc\n"
    +/*
    + * Linux zeros all registers so x29 (frame pointer) and x30 (link regi=
ster) are 0.
    + */
    +"	mov	x0, sp\n"	/* Pointer to argc, etc kernel left on the stack */
    +"	and	sp, x0, #-16\n"	/* Align stack to 16-byte boundary */
    +"	b	_start_c\n"	/* Our MI code takes it from here */
    +/* NORETURN */
    +".ltorg\n"		/* END(_start) */
    +".cfi_endproc\n"
    +".size _start, .-_start\n"
    +);
    diff --git a/stand/kboot/arch/aarch64/stat_arch.h b/stand/kboot/arch/aa=
rch64/stat_arch.h
    new file mode 100644
    index 000000000000..2462caed8682
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/stat_arch.h
    @@ -0,0 +1,29 @@
    +/*
    + * Copyright (c) 2005-2020 Rich Felker, et al.
    + *
    + * SPDX-License-Identifier: MIT
    + *
    + * Note: From the musl project
    + */
    +
    +struct host_kstat {
    +	host_dev_t st_dev;
    +	host_ino_t st_ino;
    +	host_mode_t st_mode;
    +	host_nlink_t st_nlink;
    +	host_uid_t st_uid;
    +	host_gid_t st_gid;
    +	host_dev_t st_rdev;
    +	unsigned long __pad;
    +	host_off_t st_size;
    +	host_blksize_t st_blksize;
    +	int __pad2;
    +	host_blkcnt_t st_blocks;
    +	long st_atime_sec;
    +	long st_atime_nsec;
    +	long st_mtime_sec;
    +	long st_mtime_nsec;
    +	long st_ctime_sec;
    +	long st_ctime_nsec;
    +	unsigned __pad_for_future[2];
    +};
    diff --git a/stand/kboot/arch/aarch64/syscall_nr.h b/stand/kboot/arch/a=
arch64/syscall_nr.h
    new file mode 100644
    index 000000000000..511d1fa8b2a7
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/syscall_nr.h
    @@ -0,0 +1,20 @@
    +#define SYS_close		 57
    +#define	SYS_dup			 23
    +#define SYS_fstat		 80
    +#define SYS_getdents64		 61
    +#define	SYS_getpid		172
    +#define SYS_gettimeofday	169
    +#define SYS_lseek		 62
    +#define SYS_kexec_load		104
    +#define	SYS_mkdirat		 34
    +#define SYS_mmap		222
    +#define SYS_mount		 40
    +#define	SYS_munmap		215
    +#define SYS_newfstatat		 79
    +#define SYS_openat		 56
    +#define SYS_pselect6		 72
    +#define SYS_read		 63
    +#define SYS_reboot		142
    +#define SYS_symlinkat		 36
    +#define SYS_uname		160
    +#define SYS_write		 64
    diff --git a/stand/kboot/arch/aarch64/tramp.S b/stand/kboot/arch/aarch6=
4/tramp.S
    new file mode 100644
    index 000000000000..1edb6823bdc9
    --- /dev/null
    +++ b/stand/kboot/arch/aarch64/tramp.S
    @@ -0,0 +1,67 @@
    +/*
    + * Copyright (c) 2022, Netflix, Inc.
    + *
    + * SPDX-License-Identifier: BSD-2-Clause
    + */
    +
    +/*
    + * This is the trampoline that starts the FreeBSD kernel. Since the Li=
nux kernel
    + * calls this routine with no args, and has a different environment th=
an the boot
    + * loader provides and that the kernel expects, this code is responsib=
le for setting
    + * all that up and calling the normal kernel entry point. It's analogo=
us ot the
    + * "purgatory" code in the linux kernel. Details about these operation=
s are
    + * contained in comments below. On aarch64, the kernel will start all =
the APs so
    + * we don't have to worry about them here.
    + */
    +
    +/*
    + * Keep in sync with exec.c. Kexec starts aarch64_tramp w/o any
    + * parameters, so store them here.
    + *
    + * struct trampoline_data {
    + *	uint64_t	entry;			//  0 (PA where kernel loaded)
    + *	uint64_t	modulep;		//  8 module metadata
    + * };
    + *
    + * The aarch64 _start routine assumes:
    + *  MMU      on with an identity map, or off
    + *  D-Cache: off
    + *  I-Cache: on or off
    + *  We are loaded at a 2MiB aligned address
    + *  Module data (modulep) pointer in x0
    + *
    + * Unlike EFI, we don't support copying the staging area. We tell Linu=
nx to land
    + * the kernel in its final location with the needed alignment, etc.
    + *
    + * This trampoline installs sets up the arguments the kernel expects, =
flushes
    + * the cache lines and jumps to the kernel _start address. We pass the=
 modulep
    + * pointer in x0, as _start expects.
    + */
    +	.text
    +	.globl	aarch64_tramp
    +aarch64_tramp:
    +	b	1f		/* skip over our saved args */
    +	.p2align	3
    +trampoline_data:
    +#define TRAMP_ENTRY	0
    +#define TRAMP_MODULEP	8
    +#define TRAMP_TOTAL	16
    +	.space TRAMP_TOTAL
    +#define TMPSTACKSIZE	48	/* 16 bytes for args +8 for pushq/popfq + 24 s=
pare */
    +1:
    +	adr	x2, trampoline_data
    +	ldr	x1, [x2, #TRAMP_ENTRY]
    +	ldr	x0, [x2, #TRAMP_MODULEP]
    +	br	x1
    +
    +	.p2align 4
    +	.space	TMPSTACKSIZE
    +aarch64_tramp_end:			/* padding doubles as stack */
    +
    +	.data
    +	.globl	aarch64_tramp_size
    +aarch64_tramp_size:
    +	.long	aarch64_tramp_end-aarch64_tramp
    +	.globl	aarch64_tramp_data_offset
    +aarch64_tramp_data_offset:
    +	.long	trampoline_data-aarch64_tramp
    diff --git a/stand/kboot/host_syscalls.c b/stand/kboot/host_syscalls.c
    index 771f9e128fdd..52371021f282 100644
    --- a/stand/kboot/host_syscalls.c
    +++ b/stand/kboot/host_syscalls.c
    @@ -19,10 +19,15 @@ host_dup(int fd)
     	return host_syscall(SYS_dup, fd);
     }

    +/* Same system call with different names on different Linux architectu=
res due to history */
     int
     host_fstat(int fd, struct host_kstat *sb)
     {
    +#ifdef SYS_newfstat
     	return host_syscall(SYS_newfstat, fd, (uintptr_t)sb);
    +#else
    +	return host_syscall(SYS_fstat, fd, (uintptr_t)sb);
    +#endif
     }

     int





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?7CE3657B-5DBF-43D3-BBB2-1391764A96CB>