blob: c2c8ec295d1bbf46a42d4479bd800210120d0b8d [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>
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +01008#include <cactus_def.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02009#include <debug.h>
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +000010#include <drivers/arm/pl011.h>
11#include <drivers/console.h>
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +010012#include <errno.h>
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010013#include <lib/aarch64/arch_helpers.h>
14#include <lib/xlat_tables/xlat_tables_v2.h>
15#include <lib/xlat_tables/xlat_mmu_helpers.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020016#include <plat_arm.h>
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010017#include <plat/common/platform.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020018#include <platform_def.h>
Antonio Nino Diaz2ac6f8f2018-07-02 09:04:07 +010019#include <sp_helpers.h>
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010020#include <spci_svc.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020021#include <std_svc.h>
22
23#include "cactus.h"
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +010024#include "cactus_def.h"
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020025#include "cactus_tests.h"
26
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010027#include "tftf_lib.h"
28
29#define SPM_VM_ID_FIRST (1)
30
31#define SPM_VM_GET_COUNT (0xFF01)
32#define SPM_VCPU_GET_COUNT (0xFF02)
33#define SPM_DEBUG_LOG (0xBD000000)
34
35/* Hypervisor ID at physical SPCI instance */
36#define HYP_ID (0)
37
38/* By convention, SP IDs (as opposed to VM IDs) have bit 15 set */
39#define SP_ID(x) (x | (1 << 15))
40
41typedef unsigned short spci_vm_id_t;
42typedef unsigned short spci_vm_count_t;
43typedef unsigned short spci_vcpu_count_t;
44
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020045/* Host machine information injected by the build system in the ELF file. */
46extern const char build_message[];
47extern const char version_string[];
48
Olivier Deprezafcdb7c2019-11-29 14:21:48 +010049static spci_vcpu_count_t spm_vcpu_get_count(spci_vm_id_t vm_id)
50{
51 hvc_args args = {
52 .fid = SPM_VCPU_GET_COUNT,
53 .arg1 = vm_id
54 };
55
56 hvc_ret_values ret = tftf_hvc(&args);
57
58 return ret.ret0;
59}
60
61static spci_vm_count_t spm_vm_get_count(void)
62{
63 hvc_args args = {
64 .fid = SPM_VM_GET_COUNT
65 };
66
67 hvc_ret_values ret = tftf_hvc(&args);
68
69 return ret.ret0;
70}
71
72static void spm_debug_log(char c)
73{
74 hvc_args args = {
75 .fid = SPM_DEBUG_LOG,
76 .arg1 = c
77 };
78
79 (void)tftf_hvc(&args);
80}
81
82static smc_ret_values spci_id_get(void)
83{
84 smc_args args = {
85 .fid = SPCI_ID_GET
86 };
87
88 return tftf_smc(&args);
89}
90
91static smc_ret_values spci_msg_wait(void)
92{
93 smc_args args = {
94 .fid = SPCI_MSG_WAIT
95 };
96
97 return tftf_smc(&args);
98}
99
100/* Send response through registers using direct messaging */
101static smc_ret_values spci_msg_send_direct_resp(spci_vm_id_t sender_vm_id,
102 spci_vm_id_t target_vm_id,
103 uint32_t message)
104{
105 smc_args args = {
106 .fid = SPCI_MSG_SEND_DIRECT_RESP_SMC32,
107 .arg1 = ((uint32_t)sender_vm_id << 16) | target_vm_id,
108 .arg3 = message
109 };
110
111 return tftf_smc(&args);
112}
113
114static smc_ret_values spci_error(int32_t error_code)
115{
116 smc_args args = {
117 .fid = SPCI_ERROR,
118 .arg1 = 0,
119 .arg2 = error_code
120 };
121
122 return tftf_smc(&args);
123}
124
125/*
126 *
127 * Message loop function
128 * Notice we cannot use regular print functions because this serves to both
129 * "primary" and "secondary" VMs. Secondary VM cannot access UART directly
130 * but rather through Hafnium print hypercall.
131 *
132 */
133static void __dead2 message_loop(spci_vm_id_t vm_id)
134{
135 smc_ret_values spci_ret;
136 uint32_t sp_response;
137
138 /*
139 * This initial wait call is necessary to inform SPMD that
140 * SP initialization has completed. It blocks until receiving
141 * a direct message request.
142 */
143 spci_ret = spci_msg_wait();
144
145 for (;;) {
146
147 if (spci_ret.ret0 != SPCI_MSG_SEND_DIRECT_REQ_SMC32) {
148 spci_ret = spci_error(-1);
149 continue;
150 }
151
152 if (spci_ret.ret1 != SP_ID(vm_id)) {
153 spci_ret = spci_error(-2);
154 continue;
155 }
156
157 if (spci_ret.ret2 != HYP_ID) {
158 spci_ret = spci_error(-3);
159 continue;
160 }
161
162 /*
163 * For the sake of testing, add the vm id to the
164 * received message.
165 */
166 sp_response = spci_ret.ret3 | vm_id;
167
168 /*
169 * Send a response through direct messaging then block
170 * until receiving a new message request.
171 */
172 spci_ret = spci_msg_send_direct_resp(SP_ID(vm_id),
173 HYP_ID, sp_response);
174 }
175}
176
177static const mmap_region_t cactus_mmap[] __attribute__((used)) = {
178 /* DEVICE0 area includes UART2 necessary to console */
179 MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW),
180 {0}
181};
182
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100183static void cactus_print_memory_layout(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200184{
185 NOTICE("Secure Partition memory layout:\n");
186
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100187 NOTICE(" Image regions\n");
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200188 NOTICE(" Text region : %p - %p\n",
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100189 (void *)CACTUS_TEXT_START, (void *)CACTUS_TEXT_END);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200190 NOTICE(" Read-only data region : %p - %p\n",
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100191 (void *)CACTUS_RODATA_START, (void *)CACTUS_RODATA_END);
192 NOTICE(" Data region : %p - %p\n",
193 (void *)CACTUS_DATA_START, (void *)CACTUS_DATA_END);
194 NOTICE(" BSS region : %p - %p\n",
195 (void *)CACTUS_BSS_START, (void *)CACTUS_BSS_END);
196 NOTICE(" Total image memory : %p - %p\n",
197 (void *)CACTUS_IMAGE_BASE,
198 (void *)(CACTUS_IMAGE_BASE + CACTUS_IMAGE_SIZE));
199 NOTICE(" SPM regions\n");
200 NOTICE(" SPM <-> SP buffer : %p - %p\n",
201 (void *)CACTUS_SPM_BUF_BASE,
202 (void *)(CACTUS_SPM_BUF_BASE + CACTUS_SPM_BUF_SIZE));
203 NOTICE(" NS <-> SP buffer : %p - %p\n",
204 (void *)CACTUS_NS_BUF_BASE,
205 (void *)(CACTUS_NS_BUF_BASE + CACTUS_NS_BUF_SIZE));
206 NOTICE(" Test regions\n");
207 NOTICE(" Test region : %p - %p\n",
208 (void *)CACTUS_TEST_MEM_BASE,
209 (void *)(CACTUS_TEST_MEM_BASE + CACTUS_TEST_MEM_SIZE));
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200210}
211
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100212static void cactus_plat_configure_mmu(void)
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100213{
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100214 mmap_add_region(CACTUS_TEXT_START,
215 CACTUS_TEXT_START,
216 CACTUS_TEXT_END - CACTUS_TEXT_START,
217 MT_CODE);
218 mmap_add_region(CACTUS_RODATA_START,
219 CACTUS_RODATA_START,
220 CACTUS_RODATA_END - CACTUS_RODATA_START,
221 MT_RO_DATA);
222 mmap_add_region(CACTUS_DATA_START,
223 CACTUS_DATA_START,
224 CACTUS_DATA_END - CACTUS_DATA_START,
225 MT_RW_DATA);
226 mmap_add_region(CACTUS_BSS_START,
227 CACTUS_BSS_START,
228 CACTUS_BSS_END - CACTUS_BSS_START,
229 MT_RW_DATA);
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100230
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100231 mmap_add(cactus_mmap);
232 init_xlat_tables();
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100233}
234
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100235void __dead2 cactus_main(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200236{
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100237 assert(IS_IN_EL1() != 0);
238
239 /* Clear BSS */
240 memset((void *)CACTUS_BSS_START,
241 0, CACTUS_BSS_END - CACTUS_BSS_START);
242
243 /* Configure and enable Stage-1 MMU, enable D-Cache */
244 cactus_plat_configure_mmu();
245 enable_mmu_el1(0);
246
247 /* Get current SPCI id */
248 smc_ret_values spci_id_ret = spci_id_get();
249 if (spci_id_ret.ret0 != SPCI_SUCCESS_SMC32) {
250 ERROR("SPCI_ID_GET failed.\n");
251 panic();
252 }
253
254 spci_vm_id_t spci_id = spci_id_ret.ret2 & 0xffff;
255 if (spci_id > SPM_VM_ID_FIRST) {
256 /* Indicate secondary VM start through debug log hypercall */
257 spm_debug_log('2');
258 spm_debug_log('N');
259 spm_debug_log('D');
260 spm_debug_log('\n');
261
262 /* Run straight to the message loop */
263 message_loop(spci_id);
264 }
265
266 /* Next initialization steps only performed by primary VM */
267
Antonio Nino Diaz99f4fd22018-07-03 20:25:16 +0100268 console_init(PL011_UART2_BASE,
269 PL011_UART2_CLK_IN_HZ,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200270 PL011_BAUDRATE);
271
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100272 NOTICE("Booting Cactus Secure Partition\n%s\n%s\n",
273 build_message, version_string);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200274
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100275 cactus_print_memory_layout();
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200276
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100277 NOTICE("SPCI id: %u\n", spci_id); /* Expect VM id 1 */
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200278
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100279 /* Get number of VMs */
280 NOTICE("VM count: %u\n", spm_vm_get_count());
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100281
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100282 /* Get virtual CPU count for current VM */
283 NOTICE("vCPU count: %u\n", spm_vcpu_get_count(spci_id));
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100284
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100285 /* End up to message loop */
286 message_loop(spci_id);
Antonio Nino Diaz43ef3932018-07-03 14:39:47 +0100287
Olivier Deprezafcdb7c2019-11-29 14:21:48 +0100288 /* Not reached */
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200289}