blob: 3b9018d97a20cc5973486e91061d1824ef9ce393 [file] [log] [blame]
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01001#include <stdalign.h>
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01002#include <stddef.h>
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +01003#include <stdnoreturn.h>
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01004
Andrew Scull18c78fc2018-08-20 12:57:41 +01005#include "hf/alloc.h"
6#include "hf/api.h"
7#include "hf/boot_params.h"
8#include "hf/cpio.h"
9#include "hf/cpu.h"
10#include "hf/dlog.h"
11#include "hf/load.h"
12#include "hf/mm.h"
13#include "hf/std.h"
14#include "hf/vm.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010015
Wedson Almeida Filho84a30a02018-07-23 20:05:05 +010016char ptable_buf[PAGE_SIZE * 40];
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010017
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010018/**
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010019 * Blocks the hypervisor.
20 *
21 * TODO: Determine if we want to omit strings on non-debug builds.
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010022 */
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010023noreturn void panic(const char *fmt, ...)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010024{
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010025 va_list args;
26
27 /* TODO: Block all CPUs. */
28
29 dlog("Panic: ");
30
31 va_start(args, fmt);
32 vdlog(fmt, args);
33 va_end(args);
34
35 dlog("\n");
36
37 for (;;) {
Andrew Scull7364a8e2018-07-19 15:39:29 +010038 }
Wedson Almeida Filho87009642018-07-02 10:20:07 +010039}
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010040
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010041/**
42 * Performs one-time initialisation of the hypervisor.
43 */
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010044static void one_time_init(void)
45{
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010046 struct boot_params params;
47 struct boot_params_update update;
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010048 struct memiter primary_initrd;
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010049 struct memiter cpio;
Andrew Scull80871322018-08-06 12:04:09 +010050 void *initrd;
Andrew Walbran34ce72e2018-09-13 16:47:44 +010051 size_t i;
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010052
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010053 dlog("Initialising hafnium\n");
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010054
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010055 cpu_module_init();
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010056 halloc_init((size_t)ptable_buf, sizeof(ptable_buf));
57
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010058 if (!mm_init()) {
59 panic("mm_init failed");
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010060 }
61
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010062 if (!plat_get_boot_params(&params)) {
63 panic("unable to retrieve boot params");
64 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010065
Andrew Walbran34ce72e2018-09-13 16:47:44 +010066 for (i = 0; i < params.mem_ranges_count; ++i) {
67 dlog("Memory range: 0x%x - 0x%x\n",
68 pa_addr(params.mem_ranges[i].begin),
69 pa_addr(params.mem_ranges[i].end) - 1);
70 }
71
Andrew Scull265ada92018-07-30 15:19:01 +010072 dlog("Ramdisk range: 0x%x - 0x%x\n", pa_addr(params.initrd_begin),
73 pa_addr(params.initrd_end) - 1);
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010074
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010075 /* Map initrd in, and initialise cpio parser. */
Andrew Scull80871322018-08-06 12:04:09 +010076 initrd = mm_identity_map(params.initrd_begin, params.initrd_end,
77 MM_MODE_R);
78 if (!initrd) {
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010079 panic("unable to map initrd in");
80 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010081
Andrew Scull80871322018-08-06 12:04:09 +010082 memiter_init(&cpio, initrd,
Andrew Scull265ada92018-07-30 15:19:01 +010083 pa_addr(params.initrd_end) - pa_addr(params.initrd_begin));
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010084
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010085 /* Load all VMs. */
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010086 if (!load_primary(&cpio, params.kernel_arg, &primary_initrd)) {
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010087 panic("unable to load primary VM");
88 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010089
Andrew Walbran34ce72e2018-09-13 16:47:44 +010090 update.initrd_begin = pa_from_va(va_from_ptr(primary_initrd.next));
91 update.initrd_end = pa_from_va(va_from_ptr(primary_initrd.limit));
92 /* load_secondary will add regions assigned to the secondary VMs from
93 * mem_ranges to reserved_ranges. */
94 update.reserved_ranges_count = 0;
95 if (!load_secondary(&cpio, &params, &update)) {
Wedson Almeida Filho84a30a02018-07-23 20:05:05 +010096 panic("unable to load secondary VMs");
97 }
98
Andrew Walbran34ce72e2018-09-13 16:47:44 +010099 /* Prepare to run by updating bootparams as seen by primary VM. */
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +0100100 if (!plat_update_boot_params(&update)) {
101 panic("plat_update_boot_params failed");
102 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100103
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +0100104 mm_defrag();
Wedson Almeida Filhofed69022018-07-11 15:39:12 +0100105
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +0100106 dlog("Hafnium initialisation completed\n");
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100107}
108
Wedson Almeida Filhofed69022018-07-11 15:39:12 +0100109/**
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100110 * The entry point of CPUs when they are turned on. It is supposed to initialise
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100111 * all state and return the first vCPU to run.
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100112 */
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100113struct vcpu *cpu_main(void)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100114{
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100115 struct cpu *c = cpu();
116
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +0100117 /*
118 * Do global one-time initialisation just once. We avoid using atomics
119 * by only touching the variable from cpu 0.
120 */
Wedson Almeida Filhofed69022018-07-11 15:39:12 +0100121 static volatile bool inited = false;
122 if (cpu_index(c) == 0 && !inited) {
123 inited = true;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100124 one_time_init();
Wedson Almeida Filhofed69022018-07-11 15:39:12 +0100125 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100126
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +0100127 dlog("Starting up cpu %d\n", cpu_index(c));
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100128
Wedson Almeida Filho03e767a2018-07-30 15:32:03 +0100129 if (!mm_cpu_init()) {
130 panic("mm_cpu_init failed");
131 }
132
133 vm_set_current(&primary_vm);
134
Andrew Scullf3d45592018-09-20 14:30:22 +0100135 return &primary_vm.vcpus[cpu_index(c)];
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100136}