blob: 1b641afec090f06101446b0d2d6e504922862845 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Olivier Deprezafcdb7c2019-11-29 14:21:48 +01002 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02008#include <debug.h>
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +00009#include <drivers/arm/pl011.h>
10#include <drivers/console.h>
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +010011#include <errno.h>
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010012#include <lib/aarch64/arch_helpers.h>
13#include <lib/xlat_tables/xlat_tables_v2.h>
14#include <lib/xlat_tables/xlat_mmu_helpers.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020015#include <plat_arm.h>
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010016#include <plat/common/platform.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020017#include <platform_def.h>
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010018#include <spci_svc.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020019#include <std_svc.h>
20
21#include "cactus.h"
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +010022#include "cactus_def.h"
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020023
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010024#include "tftf_lib.h"
25
26#define SPM_VM_ID_FIRST (1)
27
28#define SPM_VM_GET_COUNT (0xFF01)
29#define SPM_VCPU_GET_COUNT (0xFF02)
30#define SPM_DEBUG_LOG (0xBD000000)
31
32/* Hypervisor ID at physical SPCI instance */
33#define HYP_ID (0)
34
35/* By convention, SP IDs (as opposed to VM IDs) have bit 15 set */
36#define SP_ID(x) (x | (1 << 15))
37
38typedef unsigned short spci_vm_id_t;
39typedef unsigned short spci_vm_count_t;
40typedef unsigned short spci_vcpu_count_t;
41
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020042/* Host machine information injected by the build system in the ELF file. */
43extern const char build_message[];
44extern const char version_string[];
45
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010046static spci_vcpu_count_t spm_vcpu_get_count(spci_vm_id_t vm_id)
47{
48 hvc_args args = {
49 .fid = SPM_VCPU_GET_COUNT,
50 .arg1 = vm_id
51 };
52
53 hvc_ret_values ret = tftf_hvc(&args);
54
55 return ret.ret0;
56}
57
58static spci_vm_count_t spm_vm_get_count(void)
59{
60 hvc_args args = {
61 .fid = SPM_VM_GET_COUNT
62 };
63
64 hvc_ret_values ret = tftf_hvc(&args);
65
66 return ret.ret0;
67}
68
69static void spm_debug_log(char c)
70{
71 hvc_args args = {
72 .fid = SPM_DEBUG_LOG,
73 .arg1 = c
74 };
75
76 (void)tftf_hvc(&args);
77}
78
79static smc_ret_values spci_id_get(void)
80{
81 smc_args args = {
82 .fid = SPCI_ID_GET
83 };
84
85 return tftf_smc(&args);
86}
87
88static smc_ret_values spci_msg_wait(void)
89{
90 smc_args args = {
91 .fid = SPCI_MSG_WAIT
92 };
93
94 return tftf_smc(&args);
95}
96
97/* Send response through registers using direct messaging */
98static smc_ret_values spci_msg_send_direct_resp(spci_vm_id_t sender_vm_id,
99 spci_vm_id_t target_vm_id,
100 uint32_t message)
101{
102 smc_args args = {
103 .fid = SPCI_MSG_SEND_DIRECT_RESP_SMC32,
104 .arg1 = ((uint32_t)sender_vm_id << 16) | target_vm_id,
105 .arg3 = message
106 };
107
108 return tftf_smc(&args);
109}
110
111static smc_ret_values spci_error(int32_t error_code)
112{
113 smc_args args = {
114 .fid = SPCI_ERROR,
115 .arg1 = 0,
116 .arg2 = error_code
117 };
118
119 return tftf_smc(&args);
120}
121
122/*
123 *
124 * Message loop function
125 * Notice we cannot use regular print functions because this serves to both
126 * "primary" and "secondary" VMs. Secondary VM cannot access UART directly
127 * but rather through Hafnium print hypercall.
128 *
129 */
130static void __dead2 message_loop(spci_vm_id_t vm_id)
131{
132 smc_ret_values spci_ret;
133 uint32_t sp_response;
134
135 /*
136 * This initial wait call is necessary to inform SPMD that
137 * SP initialization has completed. It blocks until receiving
138 * a direct message request.
139 */
140 spci_ret = spci_msg_wait();
141
142 for (;;) {
143
144 if (spci_ret.ret0 != SPCI_MSG_SEND_DIRECT_REQ_SMC32) {
145 spci_ret = spci_error(-1);
146 continue;
147 }
148
149 if (spci_ret.ret1 != SP_ID(vm_id)) {
150 spci_ret = spci_error(-2);
151 continue;
152 }
153
154 if (spci_ret.ret2 != HYP_ID) {
155 spci_ret = spci_error(-3);
156 continue;
157 }
158
159 /*
160 * For the sake of testing, add the vm id to the
161 * received message.
162 */
163 sp_response = spci_ret.ret3 | vm_id;
164
165 /*
166 * Send a response through direct messaging then block
167 * until receiving a new message request.
168 */
169 spci_ret = spci_msg_send_direct_resp(SP_ID(vm_id),
170 HYP_ID, sp_response);
171 }
172}
173
174static const mmap_region_t cactus_mmap[] __attribute__((used)) = {
175 /* DEVICE0 area includes UART2 necessary to console */
176 MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW),
177 {0}
178};
179
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100180static void cactus_print_memory_layout(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200181{
182 NOTICE("Secure Partition memory layout:\n");
183
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100184 NOTICE(" Image regions\n");
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200185 NOTICE(" Text region : %p - %p\n",
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100186 (void *)CACTUS_TEXT_START, (void *)CACTUS_TEXT_END);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200187 NOTICE(" Read-only data region : %p - %p\n",
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100188 (void *)CACTUS_RODATA_START, (void *)CACTUS_RODATA_END);
189 NOTICE(" Data region : %p - %p\n",
190 (void *)CACTUS_DATA_START, (void *)CACTUS_DATA_END);
191 NOTICE(" BSS region : %p - %p\n",
192 (void *)CACTUS_BSS_START, (void *)CACTUS_BSS_END);
193 NOTICE(" Total image memory : %p - %p\n",
194 (void *)CACTUS_IMAGE_BASE,
195 (void *)(CACTUS_IMAGE_BASE + CACTUS_IMAGE_SIZE));
196 NOTICE(" SPM regions\n");
197 NOTICE(" SPM <-> SP buffer : %p - %p\n",
198 (void *)CACTUS_SPM_BUF_BASE,
199 (void *)(CACTUS_SPM_BUF_BASE + CACTUS_SPM_BUF_SIZE));
200 NOTICE(" NS <-> SP buffer : %p - %p\n",
201 (void *)CACTUS_NS_BUF_BASE,
202 (void *)(CACTUS_NS_BUF_BASE + CACTUS_NS_BUF_SIZE));
203 NOTICE(" Test regions\n");
204 NOTICE(" Test region : %p - %p\n",
205 (void *)CACTUS_TEST_MEM_BASE,
206 (void *)(CACTUS_TEST_MEM_BASE + CACTUS_TEST_MEM_SIZE));
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200207}
208
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100209static void cactus_plat_configure_mmu(void)
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100210{
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100211 mmap_add_region(CACTUS_TEXT_START,
212 CACTUS_TEXT_START,
213 CACTUS_TEXT_END - CACTUS_TEXT_START,
214 MT_CODE);
215 mmap_add_region(CACTUS_RODATA_START,
216 CACTUS_RODATA_START,
217 CACTUS_RODATA_END - CACTUS_RODATA_START,
218 MT_RO_DATA);
219 mmap_add_region(CACTUS_DATA_START,
220 CACTUS_DATA_START,
221 CACTUS_DATA_END - CACTUS_DATA_START,
222 MT_RW_DATA);
223 mmap_add_region(CACTUS_BSS_START,
224 CACTUS_BSS_START,
225 CACTUS_BSS_END - CACTUS_BSS_START,
226 MT_RW_DATA);
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100227
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100228 mmap_add(cactus_mmap);
229 init_xlat_tables();
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100230}
231
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100232void __dead2 cactus_main(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200233{
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100234 assert(IS_IN_EL1() != 0);
235
236 /* Clear BSS */
237 memset((void *)CACTUS_BSS_START,
238 0, CACTUS_BSS_END - CACTUS_BSS_START);
239
240 /* Configure and enable Stage-1 MMU, enable D-Cache */
241 cactus_plat_configure_mmu();
242 enable_mmu_el1(0);
243
244 /* Get current SPCI id */
245 smc_ret_values spci_id_ret = spci_id_get();
246 if (spci_id_ret.ret0 != SPCI_SUCCESS_SMC32) {
247 ERROR("SPCI_ID_GET failed.\n");
248 panic();
249 }
250
251 spci_vm_id_t spci_id = spci_id_ret.ret2 & 0xffff;
252 if (spci_id > SPM_VM_ID_FIRST) {
253 /* Indicate secondary VM start through debug log hypercall */
254 spm_debug_log('2');
255 spm_debug_log('N');
256 spm_debug_log('D');
257 spm_debug_log('\n');
258
259 /* Run straight to the message loop */
260 message_loop(spci_id);
261 }
262
263 /* Next initialization steps only performed by primary VM */
264
Antonio Nino Diaz99f4fd22018-07-03 20:25:16 +0100265 console_init(PL011_UART2_BASE,
266 PL011_UART2_CLK_IN_HZ,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200267 PL011_BAUDRATE);
268
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100269 NOTICE("Booting Cactus Secure Partition\n%s\n%s\n",
270 build_message, version_string);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200271
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100272 cactus_print_memory_layout();
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200273
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100274 NOTICE("SPCI id: %u\n", spci_id); /* Expect VM id 1 */
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200275
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100276 /* Get number of VMs */
277 NOTICE("VM count: %u\n", spm_vm_get_count());
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100278
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100279 /* Get virtual CPU count for current VM */
280 NOTICE("vCPU count: %u\n", spm_vcpu_get_count(spci_id));
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100281
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100282 /* End up to message loop */
283 message_loop(spci_id);
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100284
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100285 /* Not reached */
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200286}