blob: 34980865081a325b8d1841ba50e08e2d58211c31 [file] [log] [blame]
Andrew Scull7fd4bb72018-12-08 23:40:12 +00001/*
2 * Copyright 2018 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "hf/mm.h"
18
19#include "hf/arch/mm.h"
20
21#include "hftest.h"
22
23/** There must be at least two levels in the page table. */
24#define MAX_LEVEL_LOWER_BOUND 1
25
26/**
27 * This is the number of levels that are tested and is constrained as it
28 * controls the depth of recursion in the memory management code.
29 */
30#define MAX_LEVEL_UPPER_BOUND 3
31
32/** X macro to expand tests for all levels. */
33#define EXPAND_LEVEL_TESTS \
34 LEVEL_TEST(0) \
35 LEVEL_TEST(1) \
36 LEVEL_TEST(2) \
37 LEVEL_TEST(3)
38
39/* TODO: work out how to run these test against the host fake arch. */
40
41/**
42 * A block must be allowed at level 0 as this is the level which represents
43 * pages.
44 */
45TEST(arch_mm, block_allowed_at_level0)
46{
47 ASSERT_TRUE(arch_mm_is_block_allowed(0));
48}
49
50/**
51 * The maximum level must be within acceptable bounds.
52 */
53TEST(arch_mm, max_level_stage1)
54{
55 int mode = MM_MODE_STAGE1;
56 uint8_t max_level = arch_mm_max_level(mode);
57 EXPECT_GE(max_level, MAX_LEVEL_LOWER_BOUND);
58 EXPECT_LE(max_level, MAX_LEVEL_UPPER_BOUND);
59}
60
61/* TODO: initialize arch_mm and check max level of stage-2. */
62
63/**
64 * A block is present and mutually exclusive from a table.
65 */
66#define LEVEL_TEST(lvl) \
67 TEST(arch_mm, block_properties_level##lvl) \
68 { \
69 uint8_t level = lvl; \
70 uint64_t attrs = arch_mm_mode_to_attrs(0); \
71 pte_t block_pte; \
72 \
73 /* Test doesn't apply if a block is not allowed. */ \
74 if (!arch_mm_is_block_allowed(level)) { \
75 return; \
76 } \
77 \
78 block_pte = arch_mm_block_pte(level, pa_init(0x12345678000), \
79 attrs); \
80 \
81 EXPECT_TRUE(arch_mm_pte_is_present(block_pte, level)); \
82 EXPECT_TRUE(arch_mm_pte_is_block(block_pte, level)); \
83 EXPECT_FALSE(arch_mm_pte_is_table(block_pte, level)); \
84 }
85EXPAND_LEVEL_TESTS
86#undef LEVEL_TEST
Andrew Scull02b7b782018-12-10 10:47:25 +000087
88/**
89 * The address and attributes of a block must be preserved when encoding and
90 * decoding.
91 */
92#define LEVEL_TEST(lvl) \
93 TEST(arch_mm, block_addr_and_attrs_preserved_level##lvl) \
94 { \
95 uint8_t level = lvl; \
96 paddr_t addr; \
97 uint64_t attrs; \
98 pte_t block_pte; \
99 \
100 /* Test doesn't apply if a block is not allowed. */ \
101 if (!arch_mm_is_block_allowed(level)) { \
102 return; \
103 } \
104 \
105 addr = pa_init(0); \
106 attrs = arch_mm_mode_to_attrs(0); \
107 block_pte = arch_mm_block_pte(level, addr, attrs); \
108 EXPECT_EQ(arch_mm_pte_attrs(block_pte), attrs); \
109 EXPECT_EQ(pa_addr(arch_mm_block_from_pte(block_pte)), \
110 pa_addr(addr)); \
111 \
112 addr = pa_init(PAGE_SIZE * 500); \
113 attrs = arch_mm_mode_to_attrs(MM_MODE_R | MM_MODE_W); \
114 block_pte = arch_mm_block_pte(level, addr, attrs); \
115 EXPECT_EQ(arch_mm_pte_attrs(block_pte), attrs); \
116 EXPECT_EQ(pa_addr(arch_mm_block_from_pte(block_pte)), \
117 pa_addr(addr)); \
118 }
119EXPAND_LEVEL_TESTS
120#undef LEVEL_TEST