Introduce new states to support memory sharing.
Stage-1 memory remains either valid or invalid but stage-2 memory is
owned and shared between VMs. The previous concept of unmapping means to
makethe memory absent and unowned.
Change-Id: I516abfe098fa6a7a072a47e89691687a302dd725
diff --git a/test/arch/mm_test.c b/test/arch/mm_test.c
index 3498086..9bc947f 100644
--- a/test/arch/mm_test.c
+++ b/test/arch/mm_test.c
@@ -61,26 +61,97 @@
/* TODO: initialize arch_mm and check max level of stage-2. */
/**
- * A block is present and mutually exclusive from a table.
+ * An absent entry is not present, valid, a block nor a table.
*/
-#define LEVEL_TEST(lvl) \
- TEST(arch_mm, block_properties_level##lvl) \
- { \
- uint8_t level = lvl; \
- uint64_t attrs = arch_mm_mode_to_attrs(0); \
- pte_t block_pte; \
- \
- /* Test doesn't apply if a block is not allowed. */ \
- if (!arch_mm_is_block_allowed(level)) { \
- return; \
- } \
- \
- block_pte = arch_mm_block_pte(level, pa_init(0x12345678000), \
- attrs); \
- \
- EXPECT_TRUE(arch_mm_pte_is_present(block_pte, level)); \
- EXPECT_TRUE(arch_mm_pte_is_block(block_pte, level)); \
- EXPECT_FALSE(arch_mm_pte_is_table(block_pte, level)); \
+#define LEVEL_TEST(lvl) \
+ TEST(arch_mm, absent_properties_level##lvl) \
+ { \
+ uint8_t level = lvl; \
+ pte_t absent_pte; \
+ \
+ absent_pte = arch_mm_absent_pte(level); \
+ \
+ EXPECT_FALSE(arch_mm_pte_is_present(absent_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_valid(absent_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_block(absent_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_table(absent_pte, level)); \
+ }
+EXPAND_LEVEL_TESTS
+#undef LEVEL_TEST
+
+/**
+ * An invalid block is present and mutually exclusive from a table.
+ */
+#define LEVEL_TEST(lvl) \
+ TEST(arch_mm, invalid_block_properties_level##lvl) \
+ { \
+ uint8_t level = lvl; \
+ uint64_t attrs = arch_mm_mode_to_attrs(MM_MODE_INVALID); \
+ pte_t block_pte; \
+ \
+ /* Test doesn't apply if a block is not allowed. */ \
+ if (!arch_mm_is_block_allowed(level)) { \
+ return; \
+ } \
+ \
+ block_pte = arch_mm_block_pte(level, pa_init(PAGE_SIZE * 19), \
+ attrs); \
+ \
+ EXPECT_TRUE(arch_mm_pte_is_present(block_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_valid(block_pte, level)); \
+ EXPECT_TRUE(arch_mm_pte_is_block(block_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_table(block_pte, level)); \
+ }
+EXPAND_LEVEL_TESTS
+#undef LEVEL_TEST
+
+/**
+ * A valid block is present and mutually exclusive from a table.
+ */
+#define LEVEL_TEST(lvl) \
+ TEST(arch_mm, valid_block_properties_level##lvl) \
+ { \
+ uint8_t level = lvl; \
+ uint64_t attrs = arch_mm_mode_to_attrs(0); \
+ pte_t block_pte; \
+ \
+ /* Test doesn't apply if a block is not allowed. */ \
+ if (!arch_mm_is_block_allowed(level)) { \
+ return; \
+ } \
+ \
+ block_pte = arch_mm_block_pte( \
+ level, pa_init(PAGE_SIZE * 12345678), attrs); \
+ \
+ EXPECT_TRUE(arch_mm_pte_is_present(block_pte, level)); \
+ EXPECT_TRUE(arch_mm_pte_is_valid(block_pte, level)); \
+ EXPECT_TRUE(arch_mm_pte_is_block(block_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_table(block_pte, level)); \
+ }
+EXPAND_LEVEL_TESTS
+#undef LEVEL_TEST
+
+/**
+ * A table is present, valid and mutually exclusive from a block.
+ */
+#define LEVEL_TEST(lvl) \
+ TEST(arch_mm, table_properties_level##lvl) \
+ { \
+ uint8_t level = lvl; \
+ pte_t table_pte; \
+ \
+ /* Test doesn't apply to level 0 as there can't be a table. */ \
+ if (level == 0) { \
+ return; \
+ } \
+ \
+ table_pte = arch_mm_table_pte(level, \
+ pa_init(PAGE_SIZE * 999999999)); \
+ \
+ EXPECT_TRUE(arch_mm_pte_is_present(table_pte, level)); \
+ EXPECT_TRUE(arch_mm_pte_is_valid(table_pte, level)); \
+ EXPECT_FALSE(arch_mm_pte_is_block(table_pte, level)); \
+ EXPECT_TRUE(arch_mm_pte_is_table(table_pte, level)); \
}
EXPAND_LEVEL_TESTS
#undef LEVEL_TEST
@@ -109,6 +180,13 @@
EXPECT_EQ(pa_addr(arch_mm_block_from_pte(block_pte)), \
pa_addr(addr)); \
\
+ addr = pa_init(PAGE_SIZE * 17); \
+ attrs = arch_mm_mode_to_attrs(MM_MODE_INVALID); \
+ block_pte = arch_mm_block_pte(level, addr, attrs); \
+ EXPECT_EQ(arch_mm_pte_attrs(block_pte), attrs); \
+ EXPECT_EQ(pa_addr(arch_mm_block_from_pte(block_pte)), \
+ pa_addr(addr)); \
+ \
addr = pa_init(PAGE_SIZE * 500); \
attrs = arch_mm_mode_to_attrs(MM_MODE_R | MM_MODE_W); \
block_pte = arch_mm_block_pte(level, addr, attrs); \