1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #pragma once
6
7 #include <stdalign.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stdnoreturn.h>
11 #include <zircon/boot/image.h>
12 #include <zircon/boot/multiboot.h>
13 #include <zircon/compiler.h>
14
15 // x86-64 code for: `memcpy(rdi, rsi, rcx * 8); (*rax)(rsi=rbx);`
16 #define TRAMPOLINE_CODE { \
17 0xf3, 0x48, 0xa5, /* rep movsq */ \
18 0x48, 0x89, 0xde, /* mov %rbx, %rsi */ \
19 0xff, 0xe0, /* jmp *%rax */ \
20 }
21
22 // Initializers for GDT entries as uint64_t.
23 #define GDT_ENTRIES { \
24 0, /* Null entry for selector 0. */ \
25 /* 64-bit code segment with base zero, the only one we need. */ \
26 0xffffull | /* limit 15:00 */ \
27 (0b10011010ull << 40) | /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */ \
28 (0b10101111ull << 48), /* G(1) D(0) L(1) AVL(0) limit 19:16 */ \
29 }
30
31 // This is stored in some "safe" memory that won't be overwritten by
32 // the kernel immediately. It contains everything needed to copy the
33 // kernel into place and run it in 64-bit mode. Copying it into place
34 // will overwrite the code in this file, so nothing here can run after
35 // jumping to the trampoline code.
36 struct trampoline {
37 uint8_t code[sizeof((const uint8_t[])TRAMPOLINE_CODE)];
38 alignas(8) uint64_t gdt[
39 sizeof((const uint64_t[])GDT_ENTRIES) / sizeof(uint64_t)];
40 struct {
41 void* eip;
42 uint16_t cs;
43 uint16_t pad;
44 } ljmp;
45 };
46
47 // This is defined by the linker script.
48 extern uint8_t PHYS_LOAD_ADDRESS[];
49
50 noreturn void boot_zbi(const zbi_header_t* zbi,
51 const zbi_header_t* kernel_item,
52 struct trampoline* trampoline);
53
54 // This is the entry point called from multiboot-start.S. It's in the
55 // environment required by the Multiboot spec, but given a small stack
56 // and the C (regparm) calling convention.
57 noreturn void multiboot_main(uint32_t magic, multiboot_info_t* info);
58
59 void enable_64bit_paging(uintptr_t start, uintptr_t end);
60
panic(const char * msg,...)61 __PRINTFLIKE(1, 2) static inline noreturn void panic(const char* msg, ...) {
62 while (true) {
63 __builtin_trap();
64 }
65 }
66