1/* 2 * Copyright (c) 2022, Netflix, Inc. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7/* 8 * This is the trampoline that starts the FreeBSD kernel. Since the Linux kernel 9 * calls this routine with no args, and has a different environment than the boot 10 * loader provides and that the kernel expects, this code is responsible for setting 11 * all that up and calling the normal kernel entry point. It's analogous ot the 12 * "purgatory" code in the linux kernel. Details about these operations are 13 * contained in comments below. On aarch64, the kernel will start all the APs so 14 * we don't have to worry about them here. 15 */ 16 17/* 18 * Keep in sync with exec.c. Kexec starts aarch64_tramp w/o any 19 * parameters, so store them here. 20 * 21 * struct trampoline_data { 22 * uint64_t entry; // 0 (PA where kernel loaded) 23 * uint64_t modulep; // 8 module metadata 24 * uint64_t memmap_src; // 16 Linux-provided memory map PA 25 * uint64_t memmap_dst; // 24 Module data copy PA 26 * uint64_t memmap_len; // 32 Length to copy 27 * }; 28 * 29 * FreeBSD's arm64 entry point is _start which assumes: 30 * MMU on with an identity map, or off 31 * D-Cache: off 32 * I-Cache: on or off 33 * We are loaded at a 2MiB aligned address 34 * Module data (modulep) pointer in x0 35 * 36 * The rest of the boot loader tells Linux to land the kernel in its final 37 * location with the needed alignment, etc. It does this, and then we take over. 38 * 39 * The linux kernel will helpfully turn off the MMU, flush the caches, disables 40 * them, etc. It calls the tramp with two args: FDT blob address in x0 and the 41 * EL2 vectors in x1. Currently, we make use of neither of these parameters: we 42 * pass whatever dtb we think we need as part of the module data and we're a bit 43 * weak on hypervisor support at the moment. _start's requirements are all 44 * satisifed. 45 * 46 * This trampoline sets up the arguments the kernel expects and jumps to the 47 * kernel _start address. We pass the modulep pointer in x0, as _start 48 * expects. We assume that the various cache flushing, invalidation, etc that 49 * linux did during or after copying the data down is sufficient, though we may 50 * need to be mindful of cache flushing if we run in EL2 (TBD). 51 * 52 * Note, if TRAMP_MEMMAP_SRC is non-zero, then we have to copy the Linux 53 * provided UEFI memory map. It's easier to do that here. In kboot we couldn't 54 * access the physical memory, and it's a chicken and egg problem later in the 55 * kernel. 56 */ 57 58#define TRAMP_ENTRY 0 59#define TRAMP_MODULEP 8 60#define TRAMP_MEMMAP_SRC 16 61#define TRAMP_MEMMAP_DST 24 62#define TRAMP_MEMMAP_LEN 32 63#define TRAMP_TOTAL 40 64 65 .text 66 .globl tramp 67tramp: 68 adr x8, trampoline_data 69 ldr x10, [x8, #TRAMP_MEMMAP_SRC] 70 cmp x10, xzr 71 b.eq 9f 72 73 /* 74 * Copy over the memory map into area we have reserved for it. Assume 75 * the copy is a multiple of 8, since we know table entries are made up 76 * of several 64-bit quantities. 77 */ 78 ldp x11, x12, [x8, #TRAMP_MEMMAP_DST] /* x12 = len */ 791: 80 ldr x13, [x10], #8 81 str x13, [x11], #8 82 subs x12, x12, #8 83 b.hi 1b 849: 85 ldp x9, x0, [x8, #TRAMP_ENTRY] /* x0 = modulep */ 86 br x9 87 88 .p2align 4 89trampoline_data: 90 .space TRAMP_TOTAL 91#define TMPSTACKSIZE 48 /* 16 bytes for args +8 for pushq/popfq + 24 spare */ 92 .space TMPSTACKSIZE 93tramp_end: /* padding doubles as stack */ 94 95 .data 96 .globl tramp_size 97tramp_size: 98 .long tramp_end-tramp 99 .globl tramp_data_offset 100tramp_data_offset: 101 .long trampoline_data-tramp 102