blob: adf942804e6c89aeb4471deb681ea018930fbd3b [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
Andrew Scullb2910562019-09-17 14:08:27 +010011#include <stddef.h>
12
13#include "hf/api.h"
14#include "hf/boot_flow.h"
15#include "hf/boot_params.h"
16#include "hf/cpio.h"
17#include "hf/cpu.h"
18#include "hf/dlog.h"
Andrew Scull3c257452019-11-26 13:32:50 +000019#include "hf/fdt_handler.h"
Karl Meakin902af082024-11-28 14:58:38 +000020#include "hf/ffa.h"
Karl Meakind8c9fff2025-02-10 12:26:48 +000021#include "hf/ffa/init.h"
Andrew Scullb2910562019-09-17 14:08:27 +010022#include "hf/load.h"
J-Alves77b6f4f2023-03-15 11:34:49 +000023#include "hf/manifest.h"
Andrew Scullb2910562019-09-17 14:08:27 +010024#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"
Madhukar Pappireddy72454a12021-08-03 12:21:46 -050029#include "hf/plat/interrupts.h"
Andrew Scull3c257452019-11-26 13:32:50 +000030#include "hf/plat/iommu.h"
Andrew Scullb2910562019-09-17 14:08:27 +010031#include "hf/std.h"
Andrew Scullb2910562019-09-17 14:08:27 +010032
Andrew Walbran5de9c3d2020-02-10 13:35:29 +000033alignas(MM_PPOOL_ENTRY_SIZE) char ptable_buf[MM_PPOOL_ENTRY_SIZE * HEAP_PAGES];
Andrew Scullb2910562019-09-17 14:08:27 +010034
35static struct mpool ppool;
36
37/**
38 * Performs one-time initialisation of memory management for the hypervisor.
39 *
40 * This is the only C code entry point called with MMU and caching disabled. The
41 * page table returned is used to set up the MMU and caches for all subsequent
42 * code.
43 */
44void one_time_init_mm(void)
45{
46 /* Make sure the console is initialised before calling dlog. */
47 plat_console_init();
48
Karl Meakinfa1dcb82025-02-10 16:47:50 +000049 ffa_init_log();
Andrew Scullb2910562019-09-17 14:08:27 +010050
Andrew Walbran5de9c3d2020-02-10 13:35:29 +000051 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
Andrew Scullb2910562019-09-17 14:08:27 +010052 mpool_add_chunk(&ppool, ptable_buf, sizeof(ptable_buf));
53
54 if (!mm_init(&ppool)) {
55 panic("mm_init failed");
56 }
57}
58
59/**
60 * Performs one-time initialisation of the hypervisor.
61 */
62void one_time_init(void)
63{
David Brazdila2358d42020-01-27 18:51:38 +000064 struct string manifest_fname = STRING_INIT("manifest.dtb");
David Brazdilb856be62020-03-25 10:14:55 +000065 struct fdt fdt;
David Brazdila2358d42020-01-27 18:51:38 +000066 enum manifest_return_code manifest_ret;
J-Alvesdf099be2024-05-13 12:47:33 +010067 struct boot_params *params;
Andrew Scullb2910562019-09-17 14:08:27 +010068 struct boot_params_update update;
Andrew Scullb2910562019-09-17 14:08:27 +010069 struct memiter cpio;
David Brazdila2358d42020-01-27 18:51:38 +000070 struct memiter manifest_it;
Andrew Scullb2910562019-09-17 14:08:27 +010071 void *initrd;
72 size_t i;
73 struct mm_stage1_locked mm_stage1_locked;
Olivier Deprez93644652022-09-09 11:01:12 +020074 struct manifest *manifest;
Andrew Scullb2910562019-09-17 14:08:27 +010075
76 arch_one_time_init();
77
78 /* Enable locks now that mm is initialised. */
79 dlog_enable_lock();
80 mpool_enable_locks();
81
82 mm_stage1_locked = mm_lock_stage1();
83
David Brazdilb856be62020-03-25 10:14:55 +000084 if (!fdt_map(&fdt, mm_stage1_locked, plat_boot_flow_get_fdt_addr(),
85 &ppool)) {
David Brazdila2358d42020-01-27 18:51:38 +000086 panic("Unable to map FDT.");
Andrew Scull3c257452019-11-26 13:32:50 +000087 }
88
J-Alvesdf099be2024-05-13 12:47:33 +010089 static_assert(sizeof(struct boot_params) <= MM_PPOOL_ENTRY_SIZE,
90 "The sizeof boot params must fit an entry of the mpool.");
91 params = (struct boot_params *)mpool_alloc(&ppool);
92
93 if (params == NULL) {
94 panic("Could not use memory pool to allocate boot params.");
95 }
96
97 if (!boot_flow_get_params(params, &fdt)) {
David Brazdila2358d42020-01-27 18:51:38 +000098 panic("Could not parse boot params.");
Andrew Scullb2910562019-09-17 14:08:27 +010099 }
100
J-Alvesdf099be2024-05-13 12:47:33 +0100101 for (i = 0; i < params->mem_ranges_count; ++i) {
Karl Meakine8937d92024-03-19 16:04:25 +0000102 dlog_info("Memory range: %#lx - %#lx\n",
J-Alvesdf099be2024-05-13 12:47:33 +0100103 pa_addr(params->mem_ranges[i].begin),
104 pa_addr(params->mem_ranges[i].end) - 1);
Andrew Scullb2910562019-09-17 14:08:27 +0100105 }
106
Olivier Deprez62d99e32020-01-09 15:58:07 +0100107 /*
108 * Hafnium manifest is either gathered from the ramdisk or passed
109 * directly to Hafnium entry point by the earlier bootloader stage.
110 * If the ramdisk start address is non-zero it hints the manifest
111 * shall be looked up from the ramdisk. If zero, assume the address
112 * passed to Hafnium entry point is the manifest address.
113 */
J-Alvesdf099be2024-05-13 12:47:33 +0100114 if (pa_addr(params->initrd_begin)) {
Karl Meakine8937d92024-03-19 16:04:25 +0000115 dlog_info("Ramdisk range: %#lx - %#lx\n",
J-Alvesdf099be2024-05-13 12:47:33 +0100116 pa_addr(params->initrd_begin),
117 pa_addr(params->initrd_end) - 1);
Andrew Scullb2910562019-09-17 14:08:27 +0100118
Olivier Deprez62d99e32020-01-09 15:58:07 +0100119 /* Map initrd in, and initialise cpio parser. */
J-Alvesdf099be2024-05-13 12:47:33 +0100120 initrd = mm_identity_map(mm_stage1_locked, params->initrd_begin,
121 params->initrd_end, MM_MODE_R, &ppool);
Olivier Deprez62d99e32020-01-09 15:58:07 +0100122 if (!initrd) {
123 panic("Unable to map initrd.");
124 }
125
J-Alvesdf099be2024-05-13 12:47:33 +0100126 memiter_init(&cpio, initrd,
127 pa_difference(params->initrd_begin,
128 params->initrd_end));
Olivier Deprez62d99e32020-01-09 15:58:07 +0100129
130 if (!cpio_get_file(&cpio, &manifest_fname, &manifest_it)) {
131 panic("Could not find manifest in initrd.");
132 }
133 } else {
134 manifest_it = fdt.buf;
Andrew Scullb2910562019-09-17 14:08:27 +0100135 }
136
Karl Meakine8937d92024-03-19 16:04:25 +0000137 dlog_verbose("Manifest range: %p - %p (%ld bytes)\n",
138 (void *)manifest_it.next, (void *)manifest_it.limit,
139 manifest_it.limit - manifest_it.next);
Dmitrii Martynov89190c92023-02-23 20:20:10 +0300140 if (!is_aligned(manifest_it.next, 4)) {
141 panic("Manifest not aligned.");
142 }
143
Olivier Deprez62d99e32020-01-09 15:58:07 +0100144 manifest_ret = manifest_init(mm_stage1_locked, &manifest, &manifest_it,
J-Alvesdf099be2024-05-13 12:47:33 +0100145 params, &ppool);
Andrew Scullb2910562019-09-17 14:08:27 +0100146
David Brazdila2358d42020-01-27 18:51:38 +0000147 if (manifest_ret != MANIFEST_SUCCESS) {
148 panic("Could not parse manifest: %s.",
149 manifest_strerror(manifest_ret));
150 }
151
Karl Meakinfa1dcb82025-02-10 16:47:50 +0000152 ffa_init_set_tee_enabled(manifest->ffa_tee_enabled);
Madhukar Pappireddy4b6d88d2025-09-09 10:02:56 -0500153 ffa_init_version();
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}