blob: ddd90d5a999ffbf022c2e8b399903148e8a99011 [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
14#include "hf/api.h"
15#include "hf/boot_flow.h"
16#include "hf/boot_params.h"
17#include "hf/cpio.h"
18#include "hf/cpu.h"
19#include "hf/dlog.h"
Andrew Scull3c257452019-11-26 13:32:50 +000020#include "hf/fdt_handler.h"
Karl Meakin902af082024-11-28 14:58:38 +000021#include "hf/ffa.h"
Karl Meakind8c9fff2025-02-10 12:26:48 +000022#include "hf/ffa/init.h"
Andrew Scullb2910562019-09-17 14:08:27 +010023#include "hf/load.h"
J-Alves77b6f4f2023-03-15 11:34:49 +000024#include "hf/manifest.h"
Andrew Scullb2910562019-09-17 14:08:27 +010025#include "hf/mm.h"
26#include "hf/mpool.h"
27#include "hf/panic.h"
Andrew Scull3c257452019-11-26 13:32:50 +000028#include "hf/plat/boot_flow.h"
Andrew Scullb2910562019-09-17 14:08:27 +010029#include "hf/plat/console.h"
Madhukar Pappireddy72454a12021-08-03 12:21:46 -050030#include "hf/plat/interrupts.h"
Andrew Scull3c257452019-11-26 13:32:50 +000031#include "hf/plat/iommu.h"
Andrew Scullb2910562019-09-17 14:08:27 +010032#include "hf/std.h"
Andrew Scullb2910562019-09-17 14:08:27 +010033
Andrew Walbran5de9c3d2020-02-10 13:35:29 +000034alignas(MM_PPOOL_ENTRY_SIZE) char ptable_buf[MM_PPOOL_ENTRY_SIZE * HEAP_PAGES];
Andrew Scullb2910562019-09-17 14:08:27 +010035
36static struct mpool ppool;
37
38/**
39 * Performs one-time initialisation of memory management for the hypervisor.
40 *
41 * This is the only C code entry point called with MMU and caching disabled. The
42 * page table returned is used to set up the MMU and caches for all subsequent
43 * code.
44 */
45void one_time_init_mm(void)
46{
47 /* Make sure the console is initialised before calling dlog. */
48 plat_console_init();
49
Karl Meakinfa1dcb82025-02-10 16:47:50 +000050 ffa_init_log();
Andrew Scullb2910562019-09-17 14:08:27 +010051
Andrew Walbran5de9c3d2020-02-10 13:35:29 +000052 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
Andrew Scullb2910562019-09-17 14:08:27 +010053 mpool_add_chunk(&ppool, ptable_buf, sizeof(ptable_buf));
54
55 if (!mm_init(&ppool)) {
56 panic("mm_init failed");
57 }
58}
59
60/**
61 * Performs one-time initialisation of the hypervisor.
62 */
63void one_time_init(void)
64{
David Brazdila2358d42020-01-27 18:51:38 +000065 struct string manifest_fname = STRING_INIT("manifest.dtb");
David Brazdilb856be62020-03-25 10:14:55 +000066 struct fdt fdt;
David Brazdila2358d42020-01-27 18:51:38 +000067 enum manifest_return_code manifest_ret;
J-Alvesdf099be2024-05-13 12:47:33 +010068 struct boot_params *params;
Andrew Scullb2910562019-09-17 14:08:27 +010069 struct boot_params_update update;
Andrew Scullb2910562019-09-17 14:08:27 +010070 struct memiter cpio;
David Brazdila2358d42020-01-27 18:51:38 +000071 struct memiter manifest_it;
Andrew Scullb2910562019-09-17 14:08:27 +010072 void *initrd;
73 size_t i;
74 struct mm_stage1_locked mm_stage1_locked;
Olivier Deprez93644652022-09-09 11:01:12 +020075 struct manifest *manifest;
Andrew Scullb2910562019-09-17 14:08:27 +010076
77 arch_one_time_init();
78
79 /* Enable locks now that mm is initialised. */
80 dlog_enable_lock();
81 mpool_enable_locks();
82
83 mm_stage1_locked = mm_lock_stage1();
84
David Brazdilb856be62020-03-25 10:14:55 +000085 if (!fdt_map(&fdt, mm_stage1_locked, plat_boot_flow_get_fdt_addr(),
86 &ppool)) {
David Brazdila2358d42020-01-27 18:51:38 +000087 panic("Unable to map FDT.");
Andrew Scull3c257452019-11-26 13:32:50 +000088 }
89
J-Alvesdf099be2024-05-13 12:47:33 +010090 static_assert(sizeof(struct boot_params) <= MM_PPOOL_ENTRY_SIZE,
91 "The sizeof boot params must fit an entry of the mpool.");
92 params = (struct boot_params *)mpool_alloc(&ppool);
93
94 if (params == NULL) {
95 panic("Could not use memory pool to allocate boot params.");
96 }
97
98 if (!boot_flow_get_params(params, &fdt)) {
David Brazdila2358d42020-01-27 18:51:38 +000099 panic("Could not parse boot params.");
Andrew Scullb2910562019-09-17 14:08:27 +0100100 }
101
J-Alvesdf099be2024-05-13 12:47:33 +0100102 for (i = 0; i < params->mem_ranges_count; ++i) {
Karl Meakine8937d92024-03-19 16:04:25 +0000103 dlog_info("Memory range: %#lx - %#lx\n",
J-Alvesdf099be2024-05-13 12:47:33 +0100104 pa_addr(params->mem_ranges[i].begin),
105 pa_addr(params->mem_ranges[i].end) - 1);
Andrew Scullb2910562019-09-17 14:08:27 +0100106 }
107
Olivier Deprez62d99e32020-01-09 15:58:07 +0100108 /*
109 * Hafnium manifest is either gathered from the ramdisk or passed
110 * directly to Hafnium entry point by the earlier bootloader stage.
111 * If the ramdisk start address is non-zero it hints the manifest
112 * shall be looked up from the ramdisk. If zero, assume the address
113 * passed to Hafnium entry point is the manifest address.
114 */
J-Alvesdf099be2024-05-13 12:47:33 +0100115 if (pa_addr(params->initrd_begin)) {
Karl Meakine8937d92024-03-19 16:04:25 +0000116 dlog_info("Ramdisk range: %#lx - %#lx\n",
J-Alvesdf099be2024-05-13 12:47:33 +0100117 pa_addr(params->initrd_begin),
118 pa_addr(params->initrd_end) - 1);
Andrew Scullb2910562019-09-17 14:08:27 +0100119
Olivier Deprez62d99e32020-01-09 15:58:07 +0100120 /* Map initrd in, and initialise cpio parser. */
J-Alvesdf099be2024-05-13 12:47:33 +0100121 initrd = mm_identity_map(mm_stage1_locked, params->initrd_begin,
122 params->initrd_end, MM_MODE_R, &ppool);
Olivier Deprez62d99e32020-01-09 15:58:07 +0100123 if (!initrd) {
124 panic("Unable to map initrd.");
125 }
126
J-Alvesdf099be2024-05-13 12:47:33 +0100127 memiter_init(&cpio, initrd,
128 pa_difference(params->initrd_begin,
129 params->initrd_end));
Olivier Deprez62d99e32020-01-09 15:58:07 +0100130
131 if (!cpio_get_file(&cpio, &manifest_fname, &manifest_it)) {
132 panic("Could not find manifest in initrd.");
133 }
134 } else {
135 manifest_it = fdt.buf;
Andrew Scullb2910562019-09-17 14:08:27 +0100136 }
137
Karl Meakine8937d92024-03-19 16:04:25 +0000138 dlog_verbose("Manifest range: %p - %p (%ld bytes)\n",
139 (void *)manifest_it.next, (void *)manifest_it.limit,
140 manifest_it.limit - manifest_it.next);
Dmitrii Martynov89190c92023-02-23 20:20:10 +0300141 if (!is_aligned(manifest_it.next, 4)) {
142 panic("Manifest not aligned.");
143 }
144
Olivier Deprez62d99e32020-01-09 15:58:07 +0100145 manifest_ret = manifest_init(mm_stage1_locked, &manifest, &manifest_it,
J-Alvesdf099be2024-05-13 12:47:33 +0100146 params, &ppool);
Andrew Scullb2910562019-09-17 14:08:27 +0100147
David Brazdila2358d42020-01-27 18:51:38 +0000148 if (manifest_ret != MANIFEST_SUCCESS) {
149 panic("Could not parse manifest: %s.",
150 manifest_strerror(manifest_ret));
151 }
152
Karl Meakinfa1dcb82025-02-10 16:47:50 +0000153 ffa_init_set_tee_enabled(manifest->ffa_tee_enabled);
J-Alvesa09ac2d2022-06-07 13:46:59 +0100154
David Brazdilb856be62020-03-25 10:14:55 +0000155 if (!plat_iommu_init(&fdt, mm_stage1_locked, &ppool)) {
David Brazdila2358d42020-01-27 18:51:38 +0000156 panic("Could not initialize IOMMUs.");
157 }
158
J-Alvesdf099be2024-05-13 12:47:33 +0100159 cpu_module_init(params->cpu_ids, params->cpu_count);
David Brazdila2358d42020-01-27 18:51:38 +0000160
Madhukar Pappireddy72454a12021-08-03 12:21:46 -0500161 if (!plat_interrupts_controller_driver_init(&fdt, mm_stage1_locked,
162 &ppool)) {
163 panic("Could not initialize Interrupt Controller driver.");
164 }
165
Jerry Wang1c26ae72024-04-09 11:23:48 +0100166 if (!fdt_unmap(&fdt, mm_stage1_locked, &ppool)) {
167 panic("Unable to unmap FDT.");
168 }
169
Andrew Scullb2910562019-09-17 14:08:27 +0100170 /* Load all VMs. */
Andrew Scullb2910562019-09-17 14:08:27 +0100171 update.reserved_ranges_count = 0;
J-Alvesdf099be2024-05-13 12:47:33 +0100172 if (!load_vms(mm_stage1_locked, manifest, &cpio, params, &update,
Andrew Scull72b43c02019-09-18 13:53:45 +0100173 &ppool)) {
174 panic("Unable to load VMs.");
Andrew Scullb2910562019-09-17 14:08:27 +0100175 }
176
Olivier Deprez93644652022-09-09 11:01:12 +0200177 if (!boot_flow_update(mm_stage1_locked, manifest, &update, &cpio,
David Brazdile6f83222019-09-23 14:47:37 +0100178 &ppool)) {
Andrew Scullc3771072019-09-19 13:30:42 +0100179 panic("Unable to update boot flow.");
Andrew Scullb2910562019-09-17 14:08:27 +0100180 }
181
J-Alvesdf099be2024-05-13 12:47:33 +0100182 /* Free space allocated for the boot parameters. */
183 mpool_free(&ppool, params);
184
Olivier Deprez93644652022-09-09 11:01:12 +0200185 /* Now manifest parsing has completed free the resourses used. */
186 manifest_deinit(&ppool);
187
Andrew Scullb2910562019-09-17 14:08:27 +0100188 mm_unlock_stage1(&mm_stage1_locked);
189
Andrew Scullb2910562019-09-17 14:08:27 +0100190 /* Enable TLB invalidation for VM page table updates. */
191 mm_vm_enable_invalidation();
192
Daniel Boulbybaeaf2e2021-12-09 11:42:36 +0000193 /* Perform platform specfic FF-A initialization. */
Karl Meakinfa1dcb82025-02-10 16:47:50 +0000194 ffa_init(&ppool);
Raghu Krishnamurthyf5fec202022-09-30 07:25:10 -0700195
196 /* Initialise the API page pool. ppool will be empty from now on. */
197 api_init(&ppool);
Andrew Walbran41a49d82020-01-10 17:46:38 +0000198
Andrew Walbran17eebf92020-02-05 16:35:49 +0000199 dlog_info("Hafnium initialisation completed\n");
Andrew Scullb2910562019-09-17 14:08:27 +0100200}