blob: 7156e4d121d680920e17252fdfeb6d083d22f5cc [file] [log] [blame]
Andrew Scull18834872018-10-12 11:48:09 +01001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2018 The Hafnium Authors.
Andrew Scull18834872018-10-12 11:48:09 +01003 *
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
Andrew Scullfbc938a2018-08-20 14:09:28 +010017#pragma once
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010018
19#include <stdbool.h>
20#include <stddef.h>
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010021
Andrew Scull18c78fc2018-08-20 12:57:41 +010022#include "hf/addr.h"
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010023
Andrew Scull11a4a0c2018-12-29 11:38:31 +000024/*
25 * A page table entry (PTE) will take one of the following forms:
Andrew Scullc66a04d2018-12-07 13:41:56 +000026 *
27 * 1. absent : There is no mapping.
28 * 2. invalid block : Represents a block that is not in the address space.
29 * 3. valid block : Represents a block that is in the address space.
30 * 4. table : Represents a reference to a table of PTEs.
31 */
Andrew Scull80871322018-08-06 12:04:09 +010032
Andrew Scull11a4a0c2018-12-29 11:38:31 +000033/**
34 * Creates an absent PTE.
Andrew Walbran25133742018-09-28 16:28:02 +010035 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000036pte_t arch_mm_absent_pte(uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000037
38/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000039 * Creates a table PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000040 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000041pte_t arch_mm_table_pte(uint8_t level, paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000042
43/**
44 * Creates a block PTE.
45 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000046pte_t arch_mm_block_pte(uint8_t level, paddr_t pa, uint64_t attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000047
48/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000049 * Checks whether a block is allowed at the given level of the page table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000050 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000051bool arch_mm_is_block_allowed(uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000052
53/**
54 * Determines if a PTE is present i.e. it contains information and therefore
55 * needs to exist in the page table. Any non-absent PTE is present.
56 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000057bool arch_mm_pte_is_present(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000058
59/**
60 * Determines if a PTE is valid i.e. it can affect the address space. Tables and
61 * valid blocks fall into this category. Invalid blocks do not as they hold
62 * information about blocks that are not in the address space.
63 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000064bool arch_mm_pte_is_valid(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000065
66/**
67 * Determines if a PTE is a block and represents an address range, valid or
68 * invalid.
69 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000070bool arch_mm_pte_is_block(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000071
72/**
73 * Determines if a PTE represents a reference to a table of PTEs.
74 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000075bool arch_mm_pte_is_table(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000076
Andrew Scull11a4a0c2018-12-29 11:38:31 +000077/**
78 * Clears the bits of an address that are ignored by the page table. In effect,
79 * the address is rounded down to the start of the corresponding PTE range.
80 */
Andrew Scull459d3b52018-12-07 16:37:12 +000081paddr_t arch_mm_clear_pa(paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000082
83/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000084 * Extracts the start address of the PTE range.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000085 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000086paddr_t arch_mm_block_from_pte(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000087
88/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000089 * Extracts the address of the table referenced by the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000090 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000091paddr_t arch_mm_table_from_pte(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000092
93/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000094 * Extracts the attributes of the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000095 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000096uint64_t arch_mm_pte_attrs(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000097
98/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000099 * Merges the attributes of a block into those of its containing table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000100 */
Andrew Walbran2400ed22018-09-27 14:45:58 +0100101uint64_t arch_mm_combine_table_entry_attrs(uint64_t table_attrs,
102 uint64_t block_attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000103
104/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000105 * Invalidates the given range of stage-1 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000106 */
Andrew Scull459d3b52018-12-07 16:37:12 +0000107void arch_mm_invalidate_stage1_range(vaddr_t va_begin, vaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000108
109/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000110 * Invalidates the given range of stage-2 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000111 */
Andrew Scull459d3b52018-12-07 16:37:12 +0000112void arch_mm_invalidate_stage2_range(ipaddr_t va_begin, ipaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000113
114/**
115 * Writes the given range of virtual memory back to the point of unification so
116 * all cores and devices will see the updated values.
117 */
Andrew Scull459d3b52018-12-07 16:37:12 +0000118void arch_mm_write_back_dcache(void *base, size_t size);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000119
120/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000121 * Gets the maximum level allowed in the page table for stage-1.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000122 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000123uint8_t arch_mm_stage1_max_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000124
125/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000126 * Gets the maximum level allowed in the page table for stage-2.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000127 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000128uint8_t arch_mm_stage2_max_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000129
130/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000131 * Gets the number of concatenated page tables used at the root for stage-1.
132 *
133 * Tables are concatenated at the root to avoid introducing another level in the
134 * page table meaning the table is shallow and wide. Each level is an extra
135 * memory access when walking the table so keeping it shallow reduces the memory
136 * accesses to aid performance.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000137 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000138uint8_t arch_mm_stage1_root_table_count(void);
139
140/**
141 * Gets the number of concatenated page tables used at the root for stage-2.
142 */
143uint8_t arch_mm_stage2_root_table_count(void);
144
145/**
146 * Converts the mode into stage-1 attributes for a block PTE.
147 */
148uint64_t arch_mm_mode_to_stage1_attrs(int mode);
149
150/**
151 * Converts the mode into stage-2 attributes for a block PTE.
152 */
153uint64_t arch_mm_mode_to_stage2_attrs(int mode);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000154
155/**
Andrew Scull81e85092018-12-12 12:56:20 +0000156 * Converts the stage-2 block attributes back to the corresponding mode.
157 */
158int arch_mm_stage2_attrs_to_mode(uint64_t attrs);
159
160/**
Andrew Scullc280bee2019-08-14 11:11:03 +0100161 * Initializes the arch specific memory management.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000162 */
Andrew Scullc280bee2019-08-14 11:11:03 +0100163bool arch_mm_init(void);
164
165/**
166 * Enables the current CPU with arch specific memory management state.
167 */
168void arch_mm_enable(paddr_t table);