Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143106676
D22255.id63990.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D22255.id63990.diff
View Options
Index: sys/arm64/arm64/locore.S
===================================================================
--- sys/arm64/arm64/locore.S
+++ sys/arm64/arm64/locore.S
@@ -42,9 +42,11 @@
.globl kernbase
.set kernbase, KERNBASE
-#define DEVICE_MEM 0
-#define NORMAL_UNCACHED 1
-#define NORMAL_MEM 2
+/* U-Boot booti related constants. */
+#define BOOTI_MAGIC 0x644d5241
+#define UBOOT_IMAGE_OFFSET 0
+#define UBOOT_IMAGE_SIZE _end - _start
+#define UBOOT_IMAGE_FLAGS 0
/*
* We assume:
@@ -57,6 +59,21 @@
.text
.globl _start
_start:
+ /*
+ * See Documentation/arm64/booting.txt in the Linux kernel.
+ * This is needed to boot using U-Boot's booti command.
+ */
+ b 1f /* Executable code */
+ .long 0 /* Executable code */
+ .quad UBOOT_IMAGE_OFFSET /* Image load offset, little endian */
+ .quad UBOOT_IMAGE_SIZE /* Effective Image size, little endian */
+ .quad UBOOT_IMAGE_FLAGS /* kernel flags, little endian */
+ .quad 0 /* reserved */
+ .quad 0 /* reserved */
+ .quad 0 /* reserved */
+ .long BOOTI_MAGIC /* Magic number, little endian, "ARM\x64" */
+ .long 0 /* reserved (used for PE COFF offset) */
+1:
/* Drop to EL1 */
bl drop_to_el1
@@ -351,15 +368,25 @@
* Build the TTBR1 maps.
*/
- /* Find the size of the kernel */
mov x6, #(KERNBASE)
- /* Find modulep - begin */
- sub x8, x0, x6
+ and x7, x0, x6
+ cmp x7, x6
+ b.eq 1f
+ /* booted from U-Boot (using booti) */
+ ldr x7, .Lend
+ sub x8, x7, x6 /* kernel size = end - begin */
+ b 2f
+1:
+ /* booted from FreeBSD loader */
+ sub x8, x0, x6 /* size = modulep - begin */
/* Add two 2MiB pages for the module data and round up */
ldr x7, =(3 * L2_SIZE - 1)
add x8, x8, x7
+2:
/* Get the number of l2 pages to allocate, rounded down */
lsr x10, x8, #(L2_SHIFT)
+ /* Add 1 to get actual count */
+ add x10, x10, #1
/* Create the kernel space L2 table */
mov x6, x26
Index: sys/arm64/arm64/machdep.c
===================================================================
--- sys/arm64/arm64/machdep.c
+++ sys/arm64/arm64/machdep.c
@@ -923,6 +923,16 @@
vm_offset_t dtbp;
dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
+
+#if defined(FDT_DTB_STATIC)
+ /*
+ * In case the device tree blob was not retrieved (from metadata) try
+ * to use the statically embedded one.
+ */
+ if (dtbp == 0)
+ dtbp = (vm_offset_t)&fdt_static_dtb;
+#endif
+
if (dtbp == (vm_offset_t)NULL) {
printf("ERROR loading DTB\n");
return;
@@ -1041,27 +1051,22 @@
caddr_t kmdp;
bool valid;
- /* Set the module data location */
- preload_metadata = (caddr_t)(uintptr_t)(abp->modulep);
+ lastaddr = parse_boot_param(abp);
/* Find the kernel address */
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
- boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
- init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0);
link_elf_ireloc(kmdp);
#ifdef FDT
try_load_dtb(kmdp);
+ parse_bootargs(&lastaddr, abp);
#endif
efi_systbl_phys = MD_FETCH(kmdp, MODINFOMD_FW_HANDLE, vm_paddr_t);
- /* Find the address to start allocating from */
- lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
-
/* Load the physical memory ranges */
efihdr = (struct efi_map_header *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_EFI_MAP);
Index: sys/arm64/arm64/machdep_boot.c
===================================================================
--- /dev/null
+++ sys/arm64/arm64/machdep_boot.c
@@ -0,0 +1,367 @@
+/*-
+ * Copyright (c) 2019 Juniper Networks, Inc
+ * Copyright (c) 2004 Olivier Houchard
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * 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 "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ctype.h>
+#include <sys/linker.h>
+#include <sys/reboot.h>
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/vmparam.h>
+
+#ifdef FDT
+#include <contrib/libfdt/libfdt.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_subr.h>
+#include <dev/ofw/openfirm.h>
+#include <machine/pte.h>
+#include <sys/boot.h>
+#endif
+
+#ifdef FDT
+#define PRELOAD_PUSH_VALUE(type, value) do { \
+ *(type *)(preload_ptr + preload_size) = (value); \
+ preload_size += sizeof(type); \
+} while (0)
+
+#define PRELOAD_PUSH_STRING(str) do { \
+ uint32_t ssize; \
+ ssize = strlen(str) + 1; \
+ PRELOAD_PUSH_VALUE(uint32_t, ssize); \
+ strcpy((char*)(preload_ptr + preload_size), str); \
+ preload_size += ssize; \
+ preload_size = roundup(preload_size, sizeof(u_long)); \
+} while (0)
+
+static int build_l2_block_pagetable(vm_offset_t, uint64_t,
+ struct arm64_bootparams *);
+
+#define INITRD_START "linux,initrd-start"
+#define INITRD_END "linux,initrd-end"
+#define KENV_SIZE 2048
+
+static char static_kenv[KENV_SIZE];
+static caddr_t metadata_endptr;
+#endif
+
+#define PMAP_BOOTSTRAP_PAGES 2
+
+extern vm_offset_t end;
+
+/*
+ * Fake up a boot descriptor table
+ */
+static vm_offset_t
+fake_preload_metadata(void *dtb_ptr, size_t dtb_size,
+ struct arm64_bootparams *abp)
+{
+ vm_offset_t lastaddr;
+ static char fake_preload[256];
+ caddr_t preload_ptr;
+ size_t preload_size;
+
+ preload_ptr = (caddr_t)&fake_preload[0];
+ preload_size = 0;
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_NAME);
+ PRELOAD_PUSH_STRING("kernel");
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_TYPE);
+ PRELOAD_PUSH_STRING("elf kernel");
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_ADDR);
+ PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t));
+ PRELOAD_PUSH_VALUE(uint64_t, VM_MIN_KERNEL_ADDRESS);
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_SIZE);
+ PRELOAD_PUSH_VALUE(uint32_t, sizeof(size_t));
+ PRELOAD_PUSH_VALUE(uint64_t, (size_t)(&end - VM_MIN_KERNEL_ADDRESS));
+
+ lastaddr = (vm_offset_t)&end;
+ lastaddr = roundup(lastaddr, sizeof(vm_offset_t));
+
+#ifdef FDT
+ if (dtb_ptr != NULL &&
+ (build_l2_block_pagetable(lastaddr, dtb_size, abp) == 0)) {
+ /* Copy DTB to KVA space and insert it into module chain. */
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_METADATA | MODINFOMD_DTBP);
+ PRELOAD_PUSH_VALUE(uint32_t, sizeof(uint64_t));
+ PRELOAD_PUSH_VALUE(uint64_t, (uint64_t)lastaddr);
+ memmove((void *)lastaddr, dtb_ptr, dtb_size);
+ lastaddr += dtb_size;
+ }
+
+ lastaddr = roundup(lastaddr, sizeof(vm_offset_t));
+ /* End marker */
+ metadata_endptr = preload_ptr;
+#endif
+
+ PRELOAD_PUSH_VALUE(uint32_t, 0);
+ PRELOAD_PUSH_VALUE(uint32_t, 0);
+
+ preload_metadata = fake_preload;
+
+ return (lastaddr);
+}
+
+static vm_offset_t
+freebsd_parse_boot_param(struct arm64_bootparams *abp)
+{
+ vm_offset_t lastaddr;
+ void *kmdp;
+ static char *loader_envp;
+
+ preload_metadata = (caddr_t)(uintptr_t)(abp->modulep);
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp == NULL)
+ return (0);
+
+ boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+ loader_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+ init_static_kenv(loader_envp, 0);
+ lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
+
+ return (lastaddr);
+}
+
+/*
+ * Support booting from U-Boot's booti command. If modulep (register x0)
+ * is a valid address then it is a pointer to FDT.
+ */
+static vm_offset_t
+linux_parse_boot_param(struct arm64_bootparams *abp)
+{
+ uint32_t dtb_size;
+ struct fdt_header *dtb_ptr;
+
+ if (abp->modulep == 0)
+ return (fake_preload_metadata(NULL, 0, NULL));
+
+#ifdef FDT
+ /* Test if modulep (r0) point to valid DTB. */
+ dtb_ptr = (struct fdt_header *)abp->modulep;
+ if (fdt_check_header(dtb_ptr) == 0) {
+ dtb_size = fdt_totalsize(dtb_ptr);
+ return (fake_preload_metadata(dtb_ptr, dtb_size, abp));
+ }
+#endif
+
+ return 0;
+}
+
+#ifdef FDT
+/*
+ * Builds count 2 MiB page table entries.
+ * During startup, locore.S maps kernel memory in L2 page table.
+ * Create space to copy size bytes following the kernel memory.
+ * See build_l2_block_pagetable in locore.S
+ */
+static int
+build_l2_block_pagetable(vm_offset_t lastaddr, uint64_t size,
+ struct arm64_bootparams *abp)
+{
+ vm_offset_t l2_block_entry, *l2pt_entry;
+ int32_t count_2mib;
+ volatile uint64_t output_bits;
+
+ /* Number of 2MiB pages */
+ count_2mib = ((lastaddr - KERNBASE) + size) >> L2_SHIFT;
+
+ /* All the memory must not cross a 1GiB boundary */
+ if (count_2mib >= Ln_ENTRIES) {
+ printf("%s: Adding %#lx bytes makes kernel cross 1GiB boundary\n",
+ __FUNCTION__, size);
+ return EINVAL;
+ }
+
+ /* size fits within the last 2MiB page table entry */
+ if (((lastaddr - KERNBASE) >> L2_SHIFT) == count_2mib)
+ return 0;
+
+ /* Build the L2 block entry */
+ l2_block_entry = (NORMAL_MEM << 2) | L2_BLOCK | ATTR_AF;
+#ifdef SMP
+ l2_block_entry |= ATTR_SH(ATTR_SH_IS);
+#endif
+ /* Number of 2MiB pages mapped to kernel */
+ count_2mib = (lastaddr - KERNBASE) >> L2_SHIFT;
+
+ /* Go to last L2 page table entry. Each pagetable entry is 8 bytes */
+ l2pt_entry = (vm_offset_t*)((abp->kern_l1pt - PAGE_SIZE) +
+ (count_2mib << 3));
+ output_bits = (*l2pt_entry++ >> L2_SHIFT) + 1;
+
+ /* Build count 2MiB page table entries */
+ for (count_2mib = size >> L2_SHIFT; count_2mib >= 0;
+ l2pt_entry++, output_bits++, count_2mib--)
+ *l2pt_entry = (output_bits << L2_SHIFT) | l2_block_entry;
+
+ return 0;
+}
+
+/*
+ * Align start addr to 1GiB boundary and build L1 page table entry for it.
+ * See build_l1_block_pagetable in locore.S
+ */
+static void
+build_l1_block_pagetable(vm_offset_t start, struct arm64_bootparams *abp)
+{
+ vm_offset_t l1_table_idx, l1_block_entry, phy_addr, *l1_table_entry;
+
+ /* Find the table index */
+ l1_table_idx = (start >> L1_SHIFT) & Ln_ADDR_MASK;
+
+ /* Build the L1 block entry */
+ l1_block_entry = (NORMAL_UNCACHED << 2) | L1_BLOCK | ATTR_AF;
+#ifdef SMP
+ l1_block_entry |= ATTR_SH(ATTR_SH_IS);
+#endif
+
+ /* Set the physical address */
+ phy_addr = l1_block_entry | (l1_table_idx << L1_SHIFT);
+
+ /* Index of L1 pagetable. Each pagetable entry is 8 bytes */
+ l1_table_entry = (vm_offset_t*)((abp->kern_l0pt + PAGE_SIZE) +
+ (l1_table_idx << 3));
+ *l1_table_entry = phy_addr;
+}
+
+/*
+ * Copy the initrd image passed using U-Boot's booti command into
+ * KVA space.
+ */
+static void
+linux_load_initrd(vm_offset_t *lastaddr, struct arm64_bootparams *abp)
+{
+ phandle_t chosen;
+ uint64_t initrd_start = 0, initrd_end = 0;
+ uint64_t initrd_size;
+ caddr_t preload_ptr;
+ size_t preload_size = 0;
+
+ if ((chosen = OF_finddevice("/chosen")) == -1)
+ return;
+
+ if (!(OF_hasprop(chosen, INITRD_START) &&
+ OF_hasprop(chosen, INITRD_END)))
+ return;
+
+ if ((OF_getprop(chosen, INITRD_START, &initrd_start, sizeof(uint64_t))) > 0)
+ initrd_start = fdt64_to_cpu(initrd_start);
+
+ if ((OF_getprop(chosen, INITRD_END, &initrd_end, sizeof(uint64_t))) > 0)
+ initrd_end = fdt64_to_cpu(initrd_end);
+
+ if ((initrd_size = (initrd_end - initrd_start)) <= 0)
+ return;
+
+ if (build_l2_block_pagetable(*lastaddr, initrd_size, abp) != 0)
+ return;
+
+ build_l1_block_pagetable(initrd_start, abp);
+
+ /* Copy the initrd image to virtual address space */
+ memmove((void*)(*lastaddr), (void*)initrd_start, initrd_size);
+
+ preload_ptr = metadata_endptr;
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_NAME);
+ PRELOAD_PUSH_STRING("initrd");
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_TYPE);
+ PRELOAD_PUSH_STRING("md_image");
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_SIZE);
+ PRELOAD_PUSH_VALUE(uint32_t, sizeof(uint64_t));
+ PRELOAD_PUSH_VALUE(uint64_t, initrd_size);
+
+ PRELOAD_PUSH_VALUE(uint32_t, MODINFO_ADDR);
+ PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t));
+ PRELOAD_PUSH_VALUE(uint64_t, *lastaddr);
+
+ *lastaddr += initrd_size;
+ *lastaddr = roundup(*lastaddr, sizeof(vm_offset_t));
+
+ /* End marker */
+ metadata_endptr = preload_ptr;
+ PRELOAD_PUSH_VALUE(uint32_t, 0);
+ PRELOAD_PUSH_VALUE(uint32_t, 0);
+}
+
+void
+parse_bootargs(vm_offset_t *lastaddr, struct arm64_bootparams *abp)
+{
+
+ if (metadata_endptr == NULL)
+ return;
+
+ /* Booted from U-Boot */
+ linux_load_initrd(lastaddr, abp);
+
+ /*
+ * L2 PTEs map addresses in order of kernel, dtb, initrd image.
+ * Add L2 pages at the end for pmap to bootstrap L2, L3 PTEs, etc.
+ */
+ if (build_l2_block_pagetable(*lastaddr,
+ (PMAP_BOOTSTRAP_PAGES * L2_SIZE) - 1, abp) != 0)
+ return;
+ init_static_kenv(static_kenv, sizeof(static_kenv));
+ ofw_parse_bootargs();
+}
+#endif
+
+/*
+ * Parse boot parametes. Distinguish boot from loader Vs U-Boot.
+ */
+vm_offset_t
+parse_boot_param(struct arm64_bootparams *abp)
+{
+ vm_offset_t lastaddr;
+
+ if ((abp->modulep & VM_MIN_KERNEL_ADDRESS) ==
+ VM_MIN_KERNEL_ADDRESS) {
+ /* Booted from loader. */
+ lastaddr = freebsd_parse_boot_param(abp);
+ } else {
+ /* Booted from U-Boot. */
+ lastaddr = linux_parse_boot_param(abp);
+ }
+
+ return lastaddr;
+}
Index: sys/arm64/include/machdep.h
===================================================================
--- sys/arm64/include/machdep.h
+++ sys/arm64/include/machdep.h
@@ -48,5 +48,9 @@
void dbg_init(void);
void initarm(struct arm64_bootparams *);
extern void (*pagezero)(void *);
+vm_offset_t parse_boot_param(struct arm64_bootparams *);
+#ifdef FDT
+void parse_bootargs(vm_offset_t *, struct arm64_bootparams *);
+#endif
#endif /* _MACHINE_MACHDEP_H_ */
Index: sys/arm64/include/pte.h
===================================================================
--- sys/arm64/include/pte.h
+++ sys/arm64/include/pte.h
@@ -131,6 +131,10 @@
#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK)
#define pmap_l3_index(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK)
+#define DEVICE_MEM 0
+#define NORMAL_UNCACHED 1
+#define NORMAL_MEM 2
+
#endif /* !_MACHINE_PTE_H_ */
/* End of pte.h */
Index: sys/conf/Makefile.arm64
===================================================================
--- sys/conf/Makefile.arm64
+++ sys/conf/Makefile.arm64
@@ -29,6 +29,18 @@
.if !empty(DDB_ENABLED)
CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
+
+SYSTEM_LD_ = ${LD} -Bdynamic -T ldscript.$M.noheader \
+ ${_LDFLAGS} --no-warn-mismatch --warn-common --export-dynamic \
+ --dynamic-linker /red/herring \
+ -o ${FULLKERNEL}.noheader -X ${SYSTEM_OBJS} vers.o
+
+SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// $(LDSCRIPT)\
+ >ldscript.$M.noheader;\
+ ${SYSTEM_LD_}; \
+ ${OBJCOPY} -S -O binary ${FULLKERNEL}.noheader \
+ ${KERNEL_KO}.bin; \
+ rm ${FULLKERNEL}.noheader
.endif
%BEFORE_DEPEND
Index: sys/conf/files.arm64
===================================================================
--- sys/conf/files.arm64
+++ sys/conf/files.arm64
@@ -152,6 +152,7 @@
arm64/arm64/in_cksum.c optional inet | inet6
arm64/arm64/locore.S standard no-obj
arm64/arm64/machdep.c standard
+arm64/arm64/machdep_boot.c standard
arm64/arm64/mem.c standard
arm64/arm64/memcpy.S standard
arm64/arm64/memmove.S standard
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jan 27, 1:34 AM (34 m, 24 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28047949
Default Alt Text
D22255.id63990.diff (15 KB)
Attached To
Mode
D22255: Boot arm64 kernel using booti command from U-boot.
Attached
Detach File
Event Timeline
Log In to Comment