blob: 09d503e2a4b529750ccb7fe56a312dc533d11f0c [file] [log] [blame]
Andrew Scullb2910562019-09-17 14:08:27 +01001/*
2 * Copyright 2018 The Hafnium Authors.
3 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
Andrew Scullb2910562019-09-17 14:08:27 +01007 */
8
9#include "hf/arch/init.h"
10
11#include <stdalign.h>
12#include <stddef.h>
13
Olivier Deprez112d2b52020-09-30 07:39:23 +020014#include "hf/arch/other_world.h"
Andrew Walbran41a49d82020-01-10 17:46:38 +000015
Andrew Scullb2910562019-09-17 14:08:27 +010016#include "hf/api.h"
17#include "hf/boot_flow.h"
18#include "hf/boot_params.h"
19#include "hf/cpio.h"
20#include "hf/cpu.h"
21#include "hf/dlog.h"
Andrew Scull3c257452019-11-26 13:32:50 +000022#include "hf/fdt_handler.h"
Andrew Scullb2910562019-09-17 14:08:27 +010023#include "hf/load.h"
24#include "hf/mm.h"
25#include "hf/mpool.h"
26#include "hf/panic.h"
Andrew Scull3c257452019-11-26 13:32:50 +000027#include "hf/plat/boot_flow.h"
Andrew Scullb2910562019-09-17 14:08:27 +010028#include "hf/plat/console.h"
Andrew Scull3c257452019-11-26 13:32:50 +000029#include "hf/plat/iommu.h"
Andrew Scullb2910562019-09-17 14:08:27 +010030#include "hf/std.h"
31#include "hf/vm.h"
32
33#include "vmapi/hf/call.h"
34
Andrew Walbran5de9c3d2020-02-10 13:35:29 +000035alignas(MM_PPOOL_ENTRY_SIZE) char ptable_buf[MM_PPOOL_ENTRY_SIZE * HEAP_PAGES];
Andrew Scullb2910562019-09-17 14:08:27 +010036
37static struct mpool ppool;
38
39/**
40 * Performs one-time initialisation of memory management for the hypervisor.
41 *
42 * This is the only C code entry point called with MMU and caching disabled. The
43 * page table returned is used to set up the MMU and caches for all subsequent
44 * code.
45 */
46void one_time_init_mm(void)
47{
48 /* Make sure the console is initialised before calling dlog. */
49 plat_console_init();
50
J-Alves46ae4162021-04-20 12:43:01 +010051 arch_other_world_log_init();
Andrew Scullb2910562019-09-17 14:08:27 +010052
Andrew Walbran5de9c3d2020-02-10 13:35:29 +000053 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
Andrew Scullb2910562019-09-17 14:08:27 +010054 mpool_add_chunk(&ppool, ptable_buf, sizeof(ptable_buf));
55
56 if (!mm_init(&ppool)) {
57 panic("mm_init failed");
58 }
59}
60
61/**
62 * Performs one-time initialisation of the hypervisor.
63 */
64void one_time_init(void)
65{
David Brazdila2358d42020-01-27 18:51:38 +000066 struct string manifest_fname = STRING_INIT("manifest.dtb");
David Brazdilb856be62020-03-25 10:14:55 +000067 struct fdt fdt;
Andrew Scullb2910562019-09-17 14:08:27 +010068 struct manifest manifest;
David Brazdila2358d42020-01-27 18:51:38 +000069 enum manifest_return_code manifest_ret;
Andrew Scullb2910562019-09-17 14:08:27 +010070 struct boot_params params;
71 struct boot_params_update update;
Andrew Scullb2910562019-09-17 14:08:27 +010072 struct memiter cpio;
David Brazdila2358d42020-01-27 18:51:38 +000073 struct memiter manifest_it;
Andrew Scullb2910562019-09-17 14:08:27 +010074 void *initrd;
75 size_t i;
76 struct mm_stage1_locked mm_stage1_locked;
77
78 arch_one_time_init();
79
80 /* Enable locks now that mm is initialised. */
81 dlog_enable_lock();
82 mpool_enable_locks();
83
84 mm_stage1_locked = mm_lock_stage1();
85
David Brazdilb856be62020-03-25 10:14:55 +000086 if (!fdt_map(&fdt, mm_stage1_locked, plat_boot_flow_get_fdt_addr(),
87 &ppool)) {
David Brazdila2358d42020-01-27 18:51:38 +000088 panic("Unable to map FDT.");
Andrew Scull3c257452019-11-26 13:32:50 +000089 }
90
David Brazdilb856be62020-03-25 10:14:55 +000091 if (!boot_flow_get_params(&params, &fdt)) {
David Brazdila2358d42020-01-27 18:51:38 +000092 panic("Could not parse boot params.");
Andrew Scullb2910562019-09-17 14:08:27 +010093 }
94
Andrew Scullb2910562019-09-17 14:08:27 +010095 for (i = 0; i < params.mem_ranges_count; ++i) {
Andrew Walbran17eebf92020-02-05 16:35:49 +000096 dlog_info("Memory range: %#x - %#x\n",
97 pa_addr(params.mem_ranges[i].begin),
98 pa_addr(params.mem_ranges[i].end) - 1);
Andrew Scullb2910562019-09-17 14:08:27 +010099 }
100
Olivier Deprez62d99e32020-01-09 15:58:07 +0100101 /*
102 * Hafnium manifest is either gathered from the ramdisk or passed
103 * directly to Hafnium entry point by the earlier bootloader stage.
104 * If the ramdisk start address is non-zero it hints the manifest
105 * shall be looked up from the ramdisk. If zero, assume the address
106 * passed to Hafnium entry point is the manifest address.
107 */
108 if (pa_addr(params.initrd_begin)) {
109 dlog_info("Ramdisk range: %#x - %#x\n",
110 pa_addr(params.initrd_begin),
111 pa_addr(params.initrd_end) - 1);
Andrew Scullb2910562019-09-17 14:08:27 +0100112
Olivier Deprez62d99e32020-01-09 15:58:07 +0100113 /* Map initrd in, and initialise cpio parser. */
114 initrd = mm_identity_map(mm_stage1_locked, params.initrd_begin,
115 params.initrd_end, MM_MODE_R, &ppool);
116 if (!initrd) {
117 panic("Unable to map initrd.");
118 }
119
120 memiter_init(
121 &cpio, initrd,
122 pa_difference(params.initrd_begin, params.initrd_end));
123
124 if (!cpio_get_file(&cpio, &manifest_fname, &manifest_it)) {
125 panic("Could not find manifest in initrd.");
126 }
127 } else {
128 manifest_it = fdt.buf;
Andrew Scullb2910562019-09-17 14:08:27 +0100129 }
130
Olivier Deprez62d99e32020-01-09 15:58:07 +0100131 manifest_ret = manifest_init(mm_stage1_locked, &manifest, &manifest_it,
132 &ppool);
Andrew Scullb2910562019-09-17 14:08:27 +0100133
David Brazdila2358d42020-01-27 18:51:38 +0000134 if (manifest_ret != MANIFEST_SUCCESS) {
135 panic("Could not parse manifest: %s.",
136 manifest_strerror(manifest_ret));
137 }
138
David Brazdilb856be62020-03-25 10:14:55 +0000139 if (!plat_iommu_init(&fdt, mm_stage1_locked, &ppool)) {
David Brazdila2358d42020-01-27 18:51:38 +0000140 panic("Could not initialize IOMMUs.");
141 }
142
David Brazdilb856be62020-03-25 10:14:55 +0000143 if (!fdt_unmap(&fdt, mm_stage1_locked, &ppool)) {
David Brazdila2358d42020-01-27 18:51:38 +0000144 panic("Unable to unmap FDT.");
145 }
146
147 cpu_module_init(params.cpu_ids, params.cpu_count);
148
Andrew Scullb2910562019-09-17 14:08:27 +0100149 /* Load all VMs. */
Andrew Scullb2910562019-09-17 14:08:27 +0100150 update.reserved_ranges_count = 0;
Andrew Scull72b43c02019-09-18 13:53:45 +0100151 if (!load_vms(mm_stage1_locked, &manifest, &cpio, &params, &update,
152 &ppool)) {
153 panic("Unable to load VMs.");
Andrew Scullb2910562019-09-17 14:08:27 +0100154 }
155
David Brazdile6f83222019-09-23 14:47:37 +0100156 if (!boot_flow_update(mm_stage1_locked, &manifest, &update, &cpio,
157 &ppool)) {
Andrew Scullc3771072019-09-19 13:30:42 +0100158 panic("Unable to update boot flow.");
Andrew Scullb2910562019-09-17 14:08:27 +0100159 }
160
161 mm_defrag(mm_stage1_locked, &ppool);
162 mm_unlock_stage1(&mm_stage1_locked);
163
164 /* Initialise the API page pool. ppool will be empty from now on. */
165 api_init(&ppool);
166
167 /* Enable TLB invalidation for VM page table updates. */
168 mm_vm_enable_invalidation();
169
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100170 if (manifest.ffa_tee_enabled) {
Andrew Walbran41a49d82020-01-10 17:46:38 +0000171 /* Set up message buffers for TEE dispatcher. */
Olivier Deprez112d2b52020-09-30 07:39:23 +0200172 arch_other_world_init();
Andrew Walbran41a49d82020-01-10 17:46:38 +0000173 }
174
Andrew Walbran17eebf92020-02-05 16:35:49 +0000175 dlog_info("Hafnium initialisation completed\n");
Andrew Scullb2910562019-09-17 14:08:27 +0100176}