blob: f4d28c76fa3b2a18759b8ee5a59b4f721ccd1954 [file] [log] [blame]
Andrew Scull1ba470e2018-10-31 15:14:31 +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/arch/mm.h"
18
19#include "hf/mm.h"
20
21/*
Andrew Scull3681b8d2018-12-12 14:22:59 +000022 * The fake architecture uses the mode flags to represent the attributes applied
23 * to memory. The flags are shifted to avoid equality of modes and attributes.
Andrew Scull1ba470e2018-10-31 15:14:31 +000024 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000025#define PTE_ATTR_MODE_SHIFT 48
26#define PTE_ATTR_MODE_MASK \
27 ((uint64_t)(MM_MODE_R | MM_MODE_W | MM_MODE_X | MM_MODE_D | \
28 MM_MODE_INVALID | MM_MODE_UNOWNED | MM_MODE_SHARED | \
29 MM_MODE_STAGE1) \
30 << PTE_ATTR_MODE_SHIFT)
Andrew Scull1ba470e2018-10-31 15:14:31 +000031
Andrew Scull3681b8d2018-12-12 14:22:59 +000032/* The bit to distinguish a table from a block is the highest of the page bits.
33 */
34#define PTE_TABLE (UINT64_C(1) << (PAGE_BITS - 1))
35
36/* Mask for the address part of an entry. */
37#define PTE_ADDR_MASK (~(PTE_ATTR_MODE_MASK | (UINT64_C(1) << PAGE_BITS) - 1))
38
39/* Offset the bits of each level so they can't be misued. */
40#define PTE_LEVEL_SHIFT(lvl) ((lvl)*2)
41
42pte_t arch_mm_absent_pte(uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +000043{
Andrew Scull3681b8d2018-12-12 14:22:59 +000044 return ((uint64_t)(MM_MODE_INVALID | MM_MODE_UNOWNED)
45 << PTE_ATTR_MODE_SHIFT) >>
46 PTE_LEVEL_SHIFT(level);
Andrew Scull1ba470e2018-10-31 15:14:31 +000047}
48
Andrew Scull3681b8d2018-12-12 14:22:59 +000049pte_t arch_mm_table_pte(uint8_t level, paddr_t pa)
Andrew Scull1ba470e2018-10-31 15:14:31 +000050{
Andrew Scull3681b8d2018-12-12 14:22:59 +000051 return (pa_addr(pa) | PTE_TABLE) >> PTE_LEVEL_SHIFT(level);
Andrew Scull1ba470e2018-10-31 15:14:31 +000052}
53
Andrew Scull3681b8d2018-12-12 14:22:59 +000054pte_t arch_mm_block_pte(uint8_t level, paddr_t pa, uint64_t attrs)
Andrew Scull1ba470e2018-10-31 15:14:31 +000055{
Andrew Scull3681b8d2018-12-12 14:22:59 +000056 return (pa_addr(pa) | attrs) >> PTE_LEVEL_SHIFT(level);
Andrew Scull1ba470e2018-10-31 15:14:31 +000057}
58
Andrew Scull3681b8d2018-12-12 14:22:59 +000059bool arch_mm_is_block_allowed(uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +000060{
Andrew Scull1ba470e2018-10-31 15:14:31 +000061 (void)level;
62 return true;
63}
64
Andrew Scull3681b8d2018-12-12 14:22:59 +000065bool arch_mm_pte_is_present(pte_t pte, uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +000066{
Andrew Scull3681b8d2018-12-12 14:22:59 +000067 return arch_mm_pte_is_valid(pte, level) ||
68 !(((pte << PTE_LEVEL_SHIFT(level)) >> PTE_ATTR_MODE_SHIFT) &
69 MM_MODE_UNOWNED);
Andrew Scullc66a04d2018-12-07 13:41:56 +000070}
71
Andrew Scull3681b8d2018-12-12 14:22:59 +000072bool arch_mm_pte_is_valid(pte_t pte, uint8_t level)
Andrew Scullc66a04d2018-12-07 13:41:56 +000073{
Andrew Scull3681b8d2018-12-12 14:22:59 +000074 return !(((pte << PTE_LEVEL_SHIFT(level)) >> PTE_ATTR_MODE_SHIFT) &
75 MM_MODE_INVALID);
Andrew Scull1ba470e2018-10-31 15:14:31 +000076}
77
Andrew Scull3681b8d2018-12-12 14:22:59 +000078bool arch_mm_pte_is_block(pte_t pte, uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +000079{
Andrew Scull3681b8d2018-12-12 14:22:59 +000080 return arch_mm_pte_is_present(pte, level) &&
81 !arch_mm_pte_is_table(pte, level);
Andrew Scull1ba470e2018-10-31 15:14:31 +000082}
83
Andrew Scull3681b8d2018-12-12 14:22:59 +000084bool arch_mm_pte_is_table(pte_t pte, uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +000085{
Andrew Scull3681b8d2018-12-12 14:22:59 +000086 return (pte << PTE_LEVEL_SHIFT(level)) & PTE_TABLE;
Andrew Scull1ba470e2018-10-31 15:14:31 +000087}
88
89paddr_t arch_mm_clear_pa(paddr_t pa)
90{
Andrew Scull3681b8d2018-12-12 14:22:59 +000091 return pa_init(pa_addr(pa) & PTE_ADDR_MASK);
Andrew Scull1ba470e2018-10-31 15:14:31 +000092}
93
Andrew Scull3681b8d2018-12-12 14:22:59 +000094paddr_t arch_mm_block_from_pte(pte_t pte, uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +000095{
Andrew Scull3681b8d2018-12-12 14:22:59 +000096 return pa_init((pte << PTE_LEVEL_SHIFT(level)) & PTE_ADDR_MASK);
Andrew Scull1ba470e2018-10-31 15:14:31 +000097}
98
Andrew Scull3681b8d2018-12-12 14:22:59 +000099paddr_t arch_mm_table_from_pte(pte_t pte, uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +0000100{
Andrew Scull3681b8d2018-12-12 14:22:59 +0000101 return pa_init((pte << PTE_LEVEL_SHIFT(level)) & PTE_ADDR_MASK);
Andrew Scull1ba470e2018-10-31 15:14:31 +0000102}
103
Andrew Scull3681b8d2018-12-12 14:22:59 +0000104uint64_t arch_mm_pte_attrs(pte_t pte, uint8_t level)
Andrew Scull1ba470e2018-10-31 15:14:31 +0000105{
Andrew Scull3681b8d2018-12-12 14:22:59 +0000106 return ((pte << PTE_LEVEL_SHIFT(level)) & PTE_ATTR_MODE_MASK) >>
107 PTE_ATTR_MODE_SHIFT;
Andrew Scull1ba470e2018-10-31 15:14:31 +0000108}
109
110uint64_t arch_mm_combine_table_entry_attrs(uint64_t table_attrs,
111 uint64_t block_attrs)
112{
113 return table_attrs | block_attrs;
114}
115
116void arch_mm_invalidate_stage1_range(vaddr_t va_begin, vaddr_t va_end)
117{
118 /* There's no modelling of the stage-1 TLB. */
119}
120
121void arch_mm_invalidate_stage2_range(ipaddr_t va_begin, ipaddr_t va_end)
122{
123 /* There's no modelling of the stage-2 TLB. */
124}
125
126uint8_t arch_mm_max_level(int mode)
127{
128 /* All modes have 3 levels in the page table. */
129 (void)mode;
130 return 2;
131}
132
133uint8_t arch_mm_root_table_count(int mode)
134{
Andrew Scull7a789b72018-12-19 14:07:10 +0000135 /* Stage-1 has no concatenated tables but stage 2 has 4 of them. */
Andrew Scull1ba470e2018-10-31 15:14:31 +0000136 return (mode & MM_MODE_STAGE1) ? 1 : 4;
137}
138
139uint64_t arch_mm_mode_to_attrs(int mode)
140{
Andrew Scull7a789b72018-12-19 14:07:10 +0000141 /* Stage-2 ignores the device mode. */
142 if (!(mode & MM_MODE_STAGE1)) {
143 mode &= ~MM_MODE_D;
144 }
145
Andrew Scull3681b8d2018-12-12 14:22:59 +0000146 return ((uint64_t)mode << PTE_ATTR_MODE_SHIFT) & PTE_ATTR_MODE_MASK;
Andrew Scull1ba470e2018-10-31 15:14:31 +0000147}
148
149bool arch_mm_init(paddr_t table, bool first)
150{
151 /* No initialization required. */
152 (void)table;
153 (void)first;
154 return true;
155}