blob: 7b039f90ddc800d8f666443552e6b27cb411520a [file] [log] [blame]
David Brazdil7a462ec2019-08-15 12:27:47 +01001/*
2 * Copyright 2019 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.
David Brazdil7a462ec2019-08-15 12:27:47 +01007 */
8
David Brazdil52256ff2019-08-23 15:15:15 +01009#include <array>
10#include <cstdio>
Andrew Scullae9962e2019-10-03 16:51:16 +010011#include <span>
David Brazdil52256ff2019-08-23 15:15:15 +010012#include <sstream>
13
David Brazdil7a462ec2019-08-15 12:27:47 +010014#include <gmock/gmock.h>
15
16extern "C" {
17#include "hf/manifest.h"
18}
19
20namespace
21{
Andrew Scullae9962e2019-10-03 16:51:16 +010022using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010023using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010024using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010025using ::testing::NotNull;
26
David Brazdil52256ff2019-08-23 15:15:15 +010027template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010028void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010029 std::vector<char> *stdout)
30{
31 /* Create two pipes, one for stdin and one for stdout. */
32 int pipes[2][2];
33 pipe(pipes[0]);
34 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010035
David Brazdil52256ff2019-08-23 15:15:15 +010036 /* Assign FDs for reading/writing by the parent/child. */
37 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
38 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
39 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
40 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010041
David Brazdil52256ff2019-08-23 15:15:15 +010042 if (fork()) {
43 /* Parent process. */
44 std::array<char, 128> buf;
45 ssize_t res;
46
47 /* Close child FDs which won't be used. */
48 close(child_read_fd);
49 close(child_write_fd);
50
51 /* Write to stdin. */
52 for (size_t count = 0; count < stdin.size();) {
53 res = write(parent_write_fd, stdin.data() + count,
54 stdin.size() - count);
55 if (res < 0) {
56 std::cerr << "IO error" << std::endl;
57 exit(1);
58 }
59 count += res;
60 }
61 close(parent_write_fd);
62
63 /* Read from stdout. */
64 while (true) {
65 res = read(parent_read_fd, buf.data(), buf.size());
66 if (res == 0) {
67 /* EOF */
68 break;
69 } else if (res < 0) {
70 std::cerr << "IO error" << std::endl;
71 exit(1);
72 }
73 stdout->insert(stdout->end(), buf.begin(),
74 buf.begin() + res);
75 }
76 close(parent_read_fd);
77 } else {
78 /* Child process. */
79
80 /* Redirect stdin/stdout to read/write FDs. */
81 dup2(child_read_fd, STDIN_FILENO);
82 dup2(child_write_fd, STDOUT_FILENO);
83
84 /* Close all FDs which are now unused. */
85 close(child_read_fd);
86 close(child_write_fd);
87 close(parent_read_fd);
88 close(parent_write_fd);
89
90 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010091 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +010092 }
93}
94
95/**
96 * Class for programatically building a Device Tree.
97 *
98 * Usage:
99 * std::vector<char> dtb = ManifestDtBuilder()
100 * .Command1()
101 * .Command2()
102 * ...
103 * .CommandN()
104 * .Build();
105 */
106class ManifestDtBuilder
107{
108 public:
109 ManifestDtBuilder()
110 {
111 dts_ << "/dts-v1/;" << std::endl;
112 dts_ << std::endl;
113
114 /* Start root node. */
115 StartChild("/");
116 }
117
Andrew Scullae9962e2019-10-03 16:51:16 +0100118 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100119 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100120 const char *program = "./build/image/dtc.py";
121 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100122 std::vector<char> dtc_stdout;
123
124 /* Finish root node. */
125 EndChild();
126
Andrew Scullae9962e2019-10-03 16:51:16 +0100127 if (dump) {
128 Dump();
129 }
130
David Brazdil0dbb41f2019-09-09 18:03:35 +0100131 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100132 return dtc_stdout;
133 }
134
Andrew Scullae9962e2019-10-03 16:51:16 +0100135 void Dump()
136 {
137 std::cerr << dts_.str() << std::endl;
138 }
139
David Brazdil52256ff2019-08-23 15:15:15 +0100140 ManifestDtBuilder &StartChild(const std::string_view &name)
141 {
142 dts_ << name << " {" << std::endl;
143 return *this;
144 }
145
146 ManifestDtBuilder &EndChild()
147 {
148 dts_ << "};" << std::endl;
149 return *this;
150 }
151
David Brazdil74e9c3b2019-08-28 11:09:08 +0100152 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
153 &value = {"hafnium,hafnium"})
154 {
155 return StringListProperty("compatible", value);
156 }
157
David Brazdil52256ff2019-08-23 15:15:15 +0100158 ManifestDtBuilder &DebugName(const std::string_view &value)
159 {
160 return StringProperty("debug_name", value);
161 }
162
Manish Pandey6542f5c2020-04-27 14:37:46 +0100163 ManifestDtBuilder &Description(const std::string_view &value)
164 {
165 return StringProperty("description", value);
166 }
167
David Brazdil52256ff2019-08-23 15:15:15 +0100168 ManifestDtBuilder &KernelFilename(const std::string_view &value)
169 {
170 return StringProperty("kernel_filename", value);
171 }
172
David Brazdile6f83222019-09-23 14:47:37 +0100173 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
174 {
175 return StringProperty("ramdisk_filename", value);
176 }
177
David Brazdil080ee312020-02-25 15:30:30 -0800178 ManifestDtBuilder &BootAddress(uint64_t value)
179 {
180 return Integer64Property("boot_address", value);
181 }
182
Andrew Scullae9962e2019-10-03 16:51:16 +0100183 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100184 {
185 return IntegerProperty("vcpu_count", value);
186 }
187
Andrew Scullae9962e2019-10-03 16:51:16 +0100188 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100189 {
190 return IntegerProperty("mem_size", value);
191 }
192
Andrew Scullae9962e2019-10-03 16:51:16 +0100193 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
194 {
195 return IntegerListProperty("smc_whitelist", value);
196 }
197
198 ManifestDtBuilder &SmcWhitelistPermissive()
199 {
200 return BooleanProperty("smc_whitelist_permissive");
201 }
202
Olivier Deprez62d99e32020-01-09 15:58:07 +0100203 ManifestDtBuilder &LoadAddress(uint64_t value)
204 {
205 return Integer64Property("load_address", value);
206 }
207
208 ManifestDtBuilder &FfaPartition()
209 {
210 return BooleanProperty("is_ffa_partition");
211 }
212
Andrew Scullae9962e2019-10-03 16:51:16 +0100213 ManifestDtBuilder &Property(const std::string_view &name,
214 const std::string_view &value)
215 {
216 dts_ << name << " = " << value << ";" << std::endl;
217 return *this;
218 }
219
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100220 ManifestDtBuilder &Label(const std::string_view &name)
221 {
222 dts_ << name << ": ";
223 return *this;
224 }
225
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100226 ManifestDtBuilder &FfaValidManifest()
227 {
228 Compatible({"arm,ffa-manifest-1.0"});
229 Property("ffa-version", "<0x10000>");
230 Property("uuid",
231 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
232 Property("execution-ctx-count", "<1>");
233 Property("exception-level", "<2>");
234 Property("execution-state", "<0>");
235 Property("load-address", "<0x7000000>");
236 Property("entrypoint-offset", "<0x00001000>");
237 Property("xlat-granule", "<0>");
238 Property("messaging-method", "<1>");
239 return *this;
240 }
241
David Brazdil52256ff2019-08-23 15:15:15 +0100242 private:
243 ManifestDtBuilder &StringProperty(const std::string_view &name,
244 const std::string_view &value)
245 {
246 dts_ << name << " = \"" << value << "\";" << std::endl;
247 return *this;
248 }
249
David Brazdil74e9c3b2019-08-28 11:09:08 +0100250 ManifestDtBuilder &StringListProperty(
251 const std::string_view &name,
252 const std::vector<std::string_view> &value)
253 {
254 bool is_first = true;
255
256 dts_ << name << " = ";
257 for (const std::string_view &entry : value) {
258 if (is_first) {
259 is_first = false;
260 } else {
261 dts_ << ", ";
262 }
263 dts_ << "\"" << entry << "\"";
264 }
265 dts_ << ";" << std::endl;
266 return *this;
267 }
268
David Brazdil52256ff2019-08-23 15:15:15 +0100269 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100270 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100271 {
272 dts_ << name << " = <" << value << ">;" << std::endl;
273 return *this;
274 }
275
David Brazdil080ee312020-02-25 15:30:30 -0800276 ManifestDtBuilder &Integer64Property(const std::string_view &name,
277 uint64_t value)
278 {
279 uint32_t high = value >> 32;
280 uint32_t low = (uint32_t)value;
281 dts_ << name << " = <" << high << " " << low << ">;"
282 << std::endl;
283 return *this;
284 }
285
Andrew Scullae9962e2019-10-03 16:51:16 +0100286 ManifestDtBuilder &IntegerListProperty(
287 const std::string_view &name,
288 const std::vector<uint32_t> &value)
289 {
290 dts_ << name << " = < ";
291 for (const uint32_t entry : value) {
292 dts_ << entry << " ";
293 }
294 dts_ << ">;" << std::endl;
295 return *this;
296 }
297
298 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
299 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000300 dts_ << name << ";" << std::endl;
301 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100302 }
303
David Brazdil52256ff2019-08-23 15:15:15 +0100304 std::stringstream dts_;
305};
306
David Brazdila2358d42020-01-27 18:51:38 +0000307static enum manifest_return_code manifest_from_vec(struct manifest *m,
308 const std::vector<char> &vec)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100309{
David Brazdila2358d42020-01-27 18:51:38 +0000310 struct memiter it;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100311 struct mpool ppool;
312 struct mm_stage1_locked mm_stage1_locked;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100313
David Brazdila2358d42020-01-27 18:51:38 +0000314 memiter_init(&it, vec.data(), vec.size());
Olivier Deprez62d99e32020-01-09 15:58:07 +0100315 return manifest_init(mm_stage1_locked, m, &it, &ppool);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100316}
317
David Brazdil52256ff2019-08-23 15:15:15 +0100318TEST(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100319{
320 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100321 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100322
David Brazdila2358d42020-01-27 18:51:38 +0000323 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100324 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
325}
326
David Brazdil74e9c3b2019-08-28 11:09:08 +0100327TEST(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100328{
329 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100330
David Brazdil52256ff2019-08-23 15:15:15 +0100331 /* clang-format off */
332 std::vector<char> dtb = ManifestDtBuilder()
333 .StartChild("hypervisor")
334 .EndChild()
335 .Build();
336 /* clang-format on */
337
David Brazdilf4925382020-03-25 13:33:51 +0000338 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100339}
340
David Brazdil74e9c3b2019-08-28 11:09:08 +0100341TEST(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100342{
343 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100344
David Brazdil52256ff2019-08-23 15:15:15 +0100345 /* clang-format off */
346 std::vector<char> dtb = ManifestDtBuilder()
347 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100348 .Compatible({ "foo,bar" })
349 .EndChild()
350 .Build();
351 /* clang-format on */
352
David Brazdila2358d42020-01-27 18:51:38 +0000353 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100354}
355
356TEST(manifest, compatible_one_of_many)
357{
358 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100359
360 /* clang-format off */
361 std::vector<char> dtb = ManifestDtBuilder()
362 .StartChild("hypervisor")
363 .Compatible({ "foo,bar", "hafnium,hafnium" })
364 .StartChild("vm1")
365 .DebugName("primary")
366 .EndChild()
367 .EndChild()
368 .Build();
369 /* clang-format on */
370
David Brazdila2358d42020-01-27 18:51:38 +0000371 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100372}
373
374TEST(manifest, no_vm_nodes)
375{
376 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100377
378 /* clang-format off */
379 std::vector<char> dtb = ManifestDtBuilder()
380 .StartChild("hypervisor")
381 .Compatible()
382 .EndChild()
383 .Build();
384 /* clang-format on */
385
David Brazdila2358d42020-01-27 18:51:38 +0000386 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100387}
388
389static std::vector<char> gen_long_string_dtb(bool valid)
390{
391 const char last_valid[] = "1234567890123456789012345678901";
392 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100393 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
394 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100395
396 /* clang-format off */
397 return ManifestDtBuilder()
398 .StartChild("hypervisor")
399 .Compatible()
400 .StartChild("vm1")
401 .DebugName(valid ? last_valid : first_invalid)
402 .EndChild()
403 .EndChild()
404 .Build();
405 /* clang-format on */
406}
407
408TEST(manifest, long_string)
409{
410 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100411 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
412 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
413
David Brazdila2358d42020-01-27 18:51:38 +0000414 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
415 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
416 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100417}
418
419TEST(manifest, reserved_vm_id)
420{
421 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100422
423 /* clang-format off */
424 std::vector<char> dtb = ManifestDtBuilder()
425 .StartChild("hypervisor")
426 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100427 .StartChild("vm1")
428 .DebugName("primary_vm")
429 .EndChild()
430 .StartChild("vm0")
431 .DebugName("reserved_vm")
432 .VcpuCount(1)
433 .MemSize(0x1000)
434 .KernelFilename("kernel")
435 .EndChild()
436 .EndChild()
437 .Build();
438 /* clang-format on */
439
David Brazdila2358d42020-01-27 18:51:38 +0000440 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100441}
442
Andrew Scullae9962e2019-10-03 16:51:16 +0100443static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100444{
445 /* clang-format off */
446 return ManifestDtBuilder()
447 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100448 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100449 .StartChild("vm1")
450 .DebugName("primary_vm")
451 .EndChild()
452 .StartChild("vm2")
453 .DebugName("secondary_vm")
454 .VcpuCount(vcpu_count)
455 .MemSize(0x1000)
456 .KernelFilename("kernel")
457 .EndChild()
458 .EndChild()
459 .Build();
460 /* clang-format on */
461}
David Brazdil7a462ec2019-08-15 12:27:47 +0100462
463TEST(manifest, vcpu_count_limit)
464{
465 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100466 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
467 std::vector<char> dtb_first_invalid =
468 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100469
David Brazdila2358d42020-01-27 18:51:38 +0000470 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100471 ASSERT_EQ(m.vm_count, 2);
David Brazdil7a462ec2019-08-15 12:27:47 +0100472 ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
473
David Brazdila2358d42020-01-27 18:51:38 +0000474 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100475 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100476}
477
David Brazdile6f83222019-09-23 14:47:37 +0100478TEST(manifest, no_ramdisk_primary)
479{
480 struct manifest m;
David Brazdile6f83222019-09-23 14:47:37 +0100481
482 /* clang-format off */
483 std::vector<char> dtb = ManifestDtBuilder()
484 .StartChild("hypervisor")
485 .Compatible()
486 .StartChild("vm1")
487 .DebugName("primary_vm")
488 .EndChild()
489 .EndChild()
490 .Build();
491 /* clang-format on */
492
David Brazdila2358d42020-01-27 18:51:38 +0000493 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdile6f83222019-09-23 14:47:37 +0100494 ASSERT_EQ(m.vm_count, 1);
495 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
496 ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
497}
498
David Brazdil080ee312020-02-25 15:30:30 -0800499TEST(manifest, no_boot_address_primary)
500{
501 struct manifest m;
502
503 /* clang-format off */
504 std::vector<char> dtb = ManifestDtBuilder()
505 .StartChild("hypervisor")
506 .Compatible()
507 .StartChild("vm1")
508 .DebugName("primary_vm")
509 .EndChild()
510 .EndChild()
511 .Build();
512 /* clang-format on */
513
514 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
515 ASSERT_EQ(m.vm_count, 1);
516 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
517 ASSERT_EQ(m.vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
518}
519
520TEST(manifest, boot_address_primary)
521{
522 struct manifest m;
523 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
524
525 /* clang-format off */
526 std::vector<char> dtb = ManifestDtBuilder()
527 .StartChild("hypervisor")
528 .Compatible()
529 .StartChild("vm1")
530 .DebugName("primary_vm")
531 .BootAddress(addr)
532 .EndChild()
533 .EndChild()
534 .Build();
535 /* clang-format on */
536
537 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
538 ASSERT_EQ(m.vm_count, 1);
539 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
540 ASSERT_EQ(m.vm[0].primary.boot_address, addr);
541}
542
Andrew Scullb2c3a242019-11-04 13:52:36 +0000543static std::vector<char> gen_malformed_boolean_dtb(
544 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100545{
Andrew Scullae9962e2019-10-03 16:51:16 +0100546 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000547 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100548 .StartChild("hypervisor")
549 .Compatible()
550 .StartChild("vm1")
551 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000552 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000553 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100554 .EndChild()
555 .Build();
556 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000557}
Andrew Scullae9962e2019-10-03 16:51:16 +0100558
Andrew Scullb2c3a242019-11-04 13:52:36 +0000559TEST(manifest, malformed_booleans)
560{
561 struct manifest m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100562
Andrew Scullb2c3a242019-11-04 13:52:36 +0000563 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
564 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
565 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
566 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100567
David Brazdila2358d42020-01-27 18:51:38 +0000568 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000569 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000570 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000571 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000572 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000573 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000574 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000575 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100576}
577
David Brazdil7a462ec2019-08-15 12:27:47 +0100578TEST(manifest, valid)
579{
580 struct manifest m;
581 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100582
David Brazdil52256ff2019-08-23 15:15:15 +0100583 /* clang-format off */
584 std::vector<char> dtb = ManifestDtBuilder()
585 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100586 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100587 .StartChild("vm1")
588 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100589 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100590 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100591 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100592 .EndChild()
593 .StartChild("vm3")
594 .DebugName("second_secondary_vm")
595 .VcpuCount(43)
596 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100597 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100598 .EndChild()
599 .StartChild("vm2")
600 .DebugName("first_secondary_vm")
601 .VcpuCount(42)
602 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100603 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
604 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100605 .EndChild()
606 .EndChild()
607 .Build();
608 /* clang-format on */
609
David Brazdila2358d42020-01-27 18:51:38 +0000610 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100611 ASSERT_EQ(m.vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100612
613 vm = &m.vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100614 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
615 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100616 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
617 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100618 ASSERT_THAT(
619 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
620 ElementsAre(0x32000000, 0x33001111));
621 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100622
623 vm = &m.vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100624 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
625 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100626 ASSERT_EQ(vm->secondary.vcpu_count, 42);
627 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100628 ASSERT_THAT(
629 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
630 ElementsAre(0x04000000, 0x30002222, 0x31445566));
631 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100632
633 vm = &m.vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100634 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
635 ASSERT_STREQ(string_data(&vm->kernel_filename),
636 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100637 ASSERT_EQ(vm->secondary.vcpu_count, 43);
638 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100639 ASSERT_THAT(
640 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
641 IsEmpty());
642 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100643}
644
Olivier Deprez62d99e32020-01-09 15:58:07 +0100645/**
646 * Class for programatically building a Partition package.
647 */
648class Partition_package
649{
650 public:
651 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
652 char manifest_dtb[PAGE_SIZE] = {};
653
654 Partition_package(const std::vector<char> &vec)
655 {
656 // Initialise header field
657 spkg.magic = SP_PKG_HEADER_MAGIC;
658 spkg.version = SP_PKG_HEADER_VERSION;
659 spkg.pm_offset = sizeof(struct sp_pkg_header);
660 spkg.pm_size = vec.size();
661
662 // Copy dtb into package
663 std::copy(vec.begin(), vec.end(), manifest_dtb);
664 }
665};
666
667static enum manifest_return_code ffa_manifest_from_vec(
668 struct manifest *m, const std::vector<char> &vec)
669{
670 struct memiter it;
671 struct mpool ppool;
672 struct mm_stage1_locked mm_stage1_locked;
673
674 Partition_package spkg(vec);
675
676 /* clang-format off */
677 std::vector<char> core_dtb = ManifestDtBuilder()
678 .StartChild("hypervisor")
679 .Compatible()
680 .StartChild("vm1")
681 .DebugName("primary_vm")
682 .FfaPartition()
683 .LoadAddress((uint64_t)&spkg)
684 .EndChild()
685 .EndChild()
686 .Build();
687 /* clang-format on */
688
689 memiter_init(&it, core_dtb.data(), core_dtb.size());
690 return manifest_init(mm_stage1_locked, m, &it, &ppool);
691}
692
693TEST(manifest, ffa_not_compatible)
694{
695 struct manifest m;
696
697 /* clang-format off */
698 std::vector<char> dtb = ManifestDtBuilder()
699 .Compatible({ "arm,ffa-manifest-2.0" })
700 .Property("ffa-version", "<0x10000>")
701 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
702 .Property("execution-ctx-count", "<1>")
703 .Property("exception-level", "<2>")
704 .Property("execution-state", "<0>")
705 .Property("load-address", "<0x7000000>")
706 .Property("entrypoint-offset", "<0x00001000>")
707 .Property("xlat-granule", "<0>")
708 .Property("messaging-method", "<1>")
709 .Build();
710 /* clang-format on */
711
712 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
713 MANIFEST_ERROR_NOT_COMPATIBLE);
714}
715
716TEST(manifest, ffa_missing_property)
717{
718 struct manifest m;
719
720 /* clang-format off */
721 std::vector<char> dtb = ManifestDtBuilder()
722 .Compatible({ "arm,ffa-manifest-1.0" })
723 .Property("ffa-version", "<0x10000>")
724 .Build();
725 /* clang-format on */
726
727 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
728 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
729}
730
731TEST(manifest, ffa_validate_sanity_check)
732{
733 struct manifest m;
734
735 /* Incompatible version */
736 /* clang-format off */
737 std::vector<char> dtb = ManifestDtBuilder()
738 .Compatible({ "arm,ffa-manifest-1.0" })
739 .Property("ffa-version", "<0xa1>")
740 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
741 .Property("execution-ctx-count", "<1>")
742 .Property("exception-level", "<2>")
743 .Property("execution-state", "<0>")
744 .Property("load-address", "<0x7000000>")
745 .Property("entrypoint-offset", "<0x00001000>")
746 .Property("xlat-granule", "<0>")
747 .Property("messaging-method", "<1>")
748 .Build();
749 /* clang-format on */
750 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
751 MANIFEST_ERROR_NOT_COMPATIBLE);
752
753 /* Incompatible translation granule */
754 /* clang-format off */
755 dtb = ManifestDtBuilder()
756 .Compatible({ "arm,ffa-manifest-1.0" })
757 .Property("ffa-version", "<0x10000>")
758 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
759 .Property("execution-ctx-count", "<1>")
760 .Property("exception-level", "<2>")
761 .Property("execution-state", "<0>")
762 .Property("load-address", "<0x7000000>")
763 .Property("entrypoint-offset", "<0x00001000>")
764 .Property("xlat-granule", "<3>")
765 .Property("messaging-method", "<1>")
766 .Build();
767 /* clang-format on */
768 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
769 MANIFEST_ERROR_NOT_COMPATIBLE);
770
771 /* Incompatible exeption level */
772 /* clang-format off */
773 dtb = ManifestDtBuilder()
774 .Compatible({ "arm,ffa-manifest-1.0" })
775 .Property("ffa-version", "<0x10000>")
776 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
777 .Property("execution-ctx-count", "<1>")
778 .Property("exception-level", "<6>")
779 .Property("execution-state", "<0>")
780 .Property("load-address", "<0x7000000>")
781 .Property("entrypoint-offset", "<0x00001000>")
782 .Property("xlat-granule", "<0>")
783 .Property("messaging-method", "<1>")
784 .Build();
785 /* clang-format on */
786 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
787 MANIFEST_ERROR_NOT_COMPATIBLE);
788
789 /* Incompatible execution state */
790 /* clang-format off */
791 dtb = ManifestDtBuilder()
792 .Compatible({ "arm,ffa-manifest-1.0" })
793 .Property("ffa-version", "<0x10000>")
794 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
795 .Property("execution-ctx-count", "<1>")
796 .Property("exception-level", "<2>")
797 .Property("execution-state", "<2>")
798 .Property("load-address", "<0x7000000>")
799 .Property("entrypoint-offset", "<0x00001000>")
800 .Property("xlat-granule", "<0>")
801 .Property("messaging-method", "<1>")
802 .Build();
803 /* clang-format on */
804 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
805 MANIFEST_ERROR_NOT_COMPATIBLE);
806
807 /* Incompatible messaging method */
808 /* clang-format off */
809 dtb = ManifestDtBuilder()
810 .Compatible({ "arm,ffa-manifest-1.0" })
811 .Property("ffa-version", "<0x10000>")
812 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
813 .Property("execution-ctx-count", "<1>")
814 .Property("exception-level", "<2>")
815 .Property("execution-state", "<0>")
816 .Property("load-address", "<0x7000000>")
817 .Property("entrypoint-offset", "<0x00001000>")
818 .Property("xlat-granule", "<0>")
819 .Property("messaging-method", "<3>")
820 .Build();
821 /* clang-format on */
822 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
823 MANIFEST_ERROR_NOT_COMPATIBLE);
824}
825
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100826TEST(manifest, ffa_validate_rxtx_info)
827{
828 struct manifest m;
829
830 /* Not Compatible */
831 /* clang-format off */
832 std::vector<char> dtb = ManifestDtBuilder()
833 .FfaValidManifest()
834 .StartChild("rx_tx-info")
835 .Compatible({ "foo,bar" })
836 .EndChild()
837 .Build();
838 /* clang-format on */
839 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
840 MANIFEST_ERROR_NOT_COMPATIBLE);
841
842 /* Missing Properties */
843 /* clang-format off */
844 dtb = ManifestDtBuilder()
845 .FfaValidManifest()
846 .StartChild("rx_tx-info")
847 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
848 .EndChild()
849 .Build();
850 /* clang-format on */
851 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
852 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
853}
854
Manish Pandey6542f5c2020-04-27 14:37:46 +0100855TEST(manifest, ffa_validate_mem_regions)
856{
857 struct manifest m;
858
859 /* Not Compatible */
860 /* clang-format off */
861 std::vector<char> dtb = ManifestDtBuilder()
862 .FfaValidManifest()
863 .StartChild("memory-regions")
864 .Compatible({ "foo,bar" })
865 .EndChild()
866 .Build();
867 /* clang-format on */
868 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
869 MANIFEST_ERROR_NOT_COMPATIBLE);
870
871 /* Memory regions unavailable */
872 /* clang-format off */
873 dtb = ManifestDtBuilder()
874 .FfaValidManifest()
875 .StartChild("memory-regions")
876 .Compatible({ "arm,ffa-manifest-memory-regions" })
877 .EndChild()
878 .Build();
879 /* clang-format on */
880 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
881 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
882
883 /* Missing Properties */
884 /* clang-format off */
885 dtb = ManifestDtBuilder()
886 .FfaValidManifest()
887 .StartChild("memory-regions")
888 .Compatible({ "arm,ffa-manifest-memory-regions" })
889 .StartChild("test-memory")
890 .Description("test-memory")
891 .EndChild()
892 .EndChild()
893 .Build();
894 /* clang-format on */
895 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
896 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
897}
898
Manish Pandeye68e7932020-04-23 15:29:28 +0100899TEST(manifest, ffa_validate_dev_regions)
900{
901 struct manifest m;
902
903 /* Not Compatible */
904 /* clang-format off */
905 std::vector<char> dtb = ManifestDtBuilder()
906 .FfaValidManifest()
907 .StartChild("device-regions")
908 .Compatible({ "foo,bar" })
909 .EndChild()
910 .Build();
911 /* clang-format on */
912 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
913 MANIFEST_ERROR_NOT_COMPATIBLE);
914
915 /* Memory regions unavailable */
916 /* clang-format off */
917 dtb = ManifestDtBuilder()
918 .FfaValidManifest()
919 .StartChild("device-regions")
920 .Compatible({ "arm,ffa-manifest-device-regions" })
921 .EndChild()
922 .Build();
923 /* clang-format on */
924 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
925 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
926
927 /* Missing Properties */
928 /* clang-format off */
929 dtb = ManifestDtBuilder()
930 .FfaValidManifest()
931 .StartChild("device-regions")
932 .Compatible({ "arm,ffa-manifest-device-regions" })
933 .StartChild("test-device")
934 .Description("test-device")
935 .EndChild()
936 .EndChild()
937 .Build();
938 /* clang-format on */
939 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
940 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
941
942 /* Malformed interrupt list pair */
943 /* clang-format off */
944 dtb = ManifestDtBuilder()
945 .FfaValidManifest()
946 .StartChild("device-regions")
947 .Compatible({ "arm,ffa-manifest-device-regions" })
948 .StartChild("test-device")
949 .Description("test-device")
950 .Property("base-address", "<0x7200000>")
951 .Property("pages-count", "<16>")
952 .Property("attributes", "<3>")
953 .Property("smmu-id", "<1>")
954 .Property("stream-ids", "<0 1>")
955 .Property("interrupts", "<2 3>, <4>")
956 .EndChild()
957 .EndChild()
958 .Build();
959 /* clang-format on */
960 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
961 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
962}
963
Olivier Deprez62d99e32020-01-09 15:58:07 +0100964TEST(manifest, ffa_valid)
965{
966 struct manifest m;
967
968 /* clang-format off */
969 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100970 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100971 .StartChild("rx_tx-info")
972 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
973 .Property("rx-buffer", "<&rx>")
974 .Property("tx-buffer", "<&tx>")
975 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +0100976 .StartChild("memory-regions")
977 .Compatible({ "arm,ffa-manifest-memory-regions" })
978 .StartChild("test-memory")
979 .Description("test-memory")
980 .Property("base-address", "<0x7100000>")
981 .Property("pages-count", "<4>")
982 .Property("attributes", "<7>")
983 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100984 .Label("rx")
985 .StartChild("rx")
986 .Description("rx-buffer")
987 .Property("base-address", "<0x7300000>")
988 .Property("pages-count", "<1>")
989 .Property("attributes", "<1>")
990 .EndChild()
991 .Label("tx")
992 .StartChild("tx")
993 .Description("tx-buffer")
994 .Property("base-address", "<0x7310000>")
995 .Property("pages-count", "<1>")
996 .Property("attributes", "<3>")
997 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +0100998 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +0100999 .StartChild("device-regions")
1000 .Compatible({ "arm,ffa-manifest-device-regions" })
1001 .StartChild("test-device")
1002 .Description("test-device")
1003 .Property("base-address", "<0x7200000>")
1004 .Property("pages-count", "<16>")
1005 .Property("attributes", "<3>")
1006 .Property("smmu-id", "<1>")
1007 .Property("stream-ids", "<0 1>")
1008 .Property("interrupts", "<2 3>, <4 5>")
1009 .EndChild()
1010 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001011 .Build();
1012 /* clang-format on */
1013
1014 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1015
1016 ASSERT_EQ(m.vm[0].sp.ffa_version, 0x10000);
1017 ASSERT_THAT(
Fuad Tabbae4efcc32020-07-16 15:37:27 +01001018 std::span(m.vm[0].sp.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001019 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
1020 ASSERT_EQ(m.vm[0].sp.execution_ctx_count, 1);
1021 ASSERT_EQ(m.vm[0].sp.run_time_el, S_EL1);
1022 ASSERT_EQ(m.vm[0].sp.execution_state, AARCH64);
1023 ASSERT_EQ(m.vm[0].sp.load_addr, 0x7000000);
1024 ASSERT_EQ(m.vm[0].sp.ep_offset, 0x00001000);
1025 ASSERT_EQ(m.vm[0].sp.xlat_granule, PAGE_4KB);
1026 ASSERT_EQ(m.vm[0].sp.messaging_method, INDIRECT_MESSAGING);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001027 ASSERT_EQ(m.vm[0].sp.mem_regions[0].base_address, 0x7100000);
1028 ASSERT_EQ(m.vm[0].sp.mem_regions[0].page_count, 4);
1029 ASSERT_EQ(m.vm[0].sp.mem_regions[0].attributes, 7);
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001030 ASSERT_EQ(m.vm[0].sp.rxtx.available, true);
1031 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->base_address, 0x7300000);
1032 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->page_count, 1);
1033 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->attributes, 1);
1034 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->base_address, 0x7310000);
1035 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->page_count, 1);
1036 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->attributes, 3);
Manish Pandeye68e7932020-04-23 15:29:28 +01001037 ASSERT_EQ(m.vm[0].sp.dev_regions[0].base_address, 0x7200000);
1038 ASSERT_EQ(m.vm[0].sp.dev_regions[0].page_count, 16);
1039 /* Attribute is ORed with MM_MODE_D */
1040 ASSERT_EQ(m.vm[0].sp.dev_regions[0].attributes, (3 | 8));
1041 ASSERT_EQ(m.vm[0].sp.dev_regions[0].smmu_id, 1);
1042 ASSERT_EQ(m.vm[0].sp.dev_regions[0].stream_ids[0], 0);
1043 ASSERT_EQ(m.vm[0].sp.dev_regions[0].stream_ids[1], 1);
1044 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[0].id, 2);
1045 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[0].attributes, 3);
1046 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[1].id, 4);
1047 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[1].attributes, 5);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001048}
1049
David Brazdil7a462ec2019-08-15 12:27:47 +01001050} /* namespace */