blob: 11303ea362a35b68408334ab7dcd188d119dbf9b [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 *
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.
Andrew Scull18834872018-10-12 11:48:09 +01007 */
8
Andrew Scullfbc938a2018-08-20 14:09:28 +01009#pragma once
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010010
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010011#include <stddef.h>
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010012
Andrew Scull18c78fc2018-08-20 12:57:41 +010013#include "hf/addr.h"
Karl Meakin07a69ab2025-02-07 14:53:19 +000014#include "hf/mm.h"
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010015
Olivier Deprez96a2a262020-06-11 17:21:38 +020016#include "vmapi/hf/ffa.h"
17
Andrew Scull11a4a0c2018-12-29 11:38:31 +000018/**
19 * Creates an absent PTE.
Andrew Walbran25133742018-09-28 16:28:02 +010020 */
Karl Meakin07a69ab2025-02-07 14:53:19 +000021pte_t arch_mm_absent_pte(mm_level_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000022
23/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000024 * Creates a table PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000025 */
Karl Meakin07a69ab2025-02-07 14:53:19 +000026pte_t arch_mm_table_pte(mm_level_t level, paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000027
28/**
29 * Creates a block PTE.
30 */
Karl Meakin07a69ab2025-02-07 14:53:19 +000031pte_t arch_mm_block_pte(mm_level_t level, paddr_t pa, mm_attr_t attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000032
Karl Meakin23122e12025-02-05 14:44:20 +000033enum mm_pte_type arch_mm_pte_type(pte_t pte, mm_level_t level);
34
Andrew Scull11a4a0c2018-12-29 11:38:31 +000035/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000036 * Checks whether a block is allowed at the given level of the page table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000037 */
Karl Meakin07a69ab2025-02-07 14:53:19 +000038bool arch_mm_is_block_allowed(mm_level_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000039
Karl Meakin23122e12025-02-05 14:44:20 +000040static inline bool arch_mm_pte_is_absent(pte_t pte, mm_level_t level)
41{
42 return arch_mm_pte_type(pte, level) == PTE_TYPE_ABSENT;
43}
44
Andrew Scullc66a04d2018-12-07 13:41:56 +000045/**
46 * Determines if a PTE is present i.e. it contains information and therefore
47 * needs to exist in the page table. Any non-absent PTE is present.
48 */
Karl Meakin23122e12025-02-05 14:44:20 +000049static inline bool arch_mm_pte_is_present(pte_t pte, mm_level_t level)
50{
51 return !arch_mm_pte_is_absent(pte, level);
52}
Andrew Scullc66a04d2018-12-07 13:41:56 +000053
54/**
55 * Determines if a PTE is valid i.e. it can affect the address space. Tables and
56 * valid blocks fall into this category. Invalid blocks do not as they hold
57 * information about blocks that are not in the address space.
58 */
Karl Meakin23122e12025-02-05 14:44:20 +000059static inline bool arch_mm_pte_is_valid(pte_t pte, mm_level_t level)
60{
61 switch (arch_mm_pte_type(pte, level)) {
62 case PTE_TYPE_ABSENT:
63 case PTE_TYPE_INVALID_BLOCK:
64 return false;
65 case PTE_TYPE_VALID_BLOCK:
66 case PTE_TYPE_TABLE:
67 return true;
68 }
69}
Andrew Scullc66a04d2018-12-07 13:41:56 +000070
71/**
72 * Determines if a PTE is a block and represents an address range, valid or
73 * invalid.
74 */
Karl Meakin23122e12025-02-05 14:44:20 +000075static inline bool arch_mm_pte_is_block(pte_t pte, mm_level_t level)
76{
77 switch (arch_mm_pte_type(pte, level)) {
78 case PTE_TYPE_ABSENT:
79 case PTE_TYPE_TABLE:
80 return false;
81 case PTE_TYPE_INVALID_BLOCK:
82 case PTE_TYPE_VALID_BLOCK:
83 return true;
84 }
85}
Andrew Scullc66a04d2018-12-07 13:41:56 +000086
87/**
88 * Determines if a PTE represents a reference to a table of PTEs.
89 */
Karl Meakin23122e12025-02-05 14:44:20 +000090static inline bool arch_mm_pte_is_table(pte_t pte, mm_level_t level)
91{
92 return arch_mm_pte_type(pte, level) == PTE_TYPE_TABLE;
93}
Andrew Scullc66a04d2018-12-07 13:41:56 +000094
Andrew Scull11a4a0c2018-12-29 11:38:31 +000095/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000096 * Extracts the start address of the PTE range.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000097 */
Karl Meakin07a69ab2025-02-07 14:53:19 +000098paddr_t arch_mm_block_from_pte(pte_t pte, mm_level_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000099
100/**
Karl Meakinaacfd4f2025-02-08 19:30:52 +0000101 * Extracts the table referenced by the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000102 */
Karl Meakinaacfd4f2025-02-08 19:30:52 +0000103struct mm_page_table *arch_mm_table_from_pte(pte_t pte, mm_level_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000104
105/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000106 * Extracts the attributes of the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000107 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000108mm_attr_t arch_mm_pte_attrs(pte_t pte, mm_level_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000109
110/**
Karl Meakin23122e12025-02-05 14:44:20 +0000111 * Merges the attributes of a block into those of its parent table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000112 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000113mm_attr_t arch_mm_combine_table_entry_attrs(mm_attr_t table_attrs,
114 mm_attr_t block_attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000115
116/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000117 * Invalidates the given range of stage-1 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000118 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000119void arch_mm_invalidate_stage1_range(ffa_id_t asid, vaddr_t va_begin,
Raghu Krishnamurthy8fdd6df2021-02-03 18:30:59 -0800120 vaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000121
122/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000123 * Invalidates the given range of stage-2 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000124 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000125void arch_mm_invalidate_stage2_range(ffa_id_t vmid, ipaddr_t va_begin,
Olivier Deprez6f400372022-03-07 09:31:08 +0100126 ipaddr_t va_end, bool non_secure);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000127
128/**
Andrew Scullc059fbe2019-09-12 12:58:40 +0100129 * Writes back the given range of virtual memory to such a point that all cores
130 * and devices will see the updated values. The corresponding cache lines are
131 * also invalidated.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000132 */
Andrew Scullc059fbe2019-09-12 12:58:40 +0100133void arch_mm_flush_dcache(void *base, size_t size);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000134
135/**
Arunachalam Ganapathy0f0f7062022-01-26 17:09:53 +0000136 * Sets the maximum level allowed in the page table for stage-1.
137 */
Karl Meakina3a9f952025-02-08 00:11:16 +0000138void arch_mm_stage1_root_level_set(uint32_t pa_bits);
Arunachalam Ganapathy0f0f7062022-01-26 17:09:53 +0000139
140/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000141 * Gets the maximum level allowed in the page table for stage-1.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000142 */
Karl Meakina3a9f952025-02-08 00:11:16 +0000143mm_level_t arch_mm_stage1_root_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000144
145/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000146 * Gets the maximum level allowed in the page table for stage-2.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000147 */
Karl Meakina3a9f952025-02-08 00:11:16 +0000148mm_level_t arch_mm_stage2_root_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000149
150/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000151 * Gets the number of concatenated page tables used at the root for stage-1.
152 *
153 * Tables are concatenated at the root to avoid introducing another level in the
154 * page table meaning the table is shallow and wide. Each level is an extra
155 * memory access when walking the table so keeping it shallow reduces the memory
156 * accesses to aid performance.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000157 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000158uint8_t arch_mm_stage1_root_table_count(void);
159
160/**
161 * Gets the number of concatenated page tables used at the root for stage-2.
162 */
163uint8_t arch_mm_stage2_root_table_count(void);
164
165/**
166 * Converts the mode into stage-1 attributes for a block PTE.
167 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000168mm_attr_t arch_mm_mode_to_stage1_attrs(mm_mode_t mode);
Andrew Scullda3df7f2019-01-05 17:49:27 +0000169
170/**
171 * Converts the mode into stage-2 attributes for a block PTE.
172 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000173mm_attr_t arch_mm_mode_to_stage2_attrs(mm_mode_t mode);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000174
175/**
Andrew Scull81e85092018-12-12 12:56:20 +0000176 * Converts the stage-2 block attributes back to the corresponding mode.
177 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000178mm_mode_t arch_mm_stage2_attrs_to_mode(mm_attr_t attrs);
Andrew Scull81e85092018-12-12 12:56:20 +0000179
180/**
Raghu Krishnamurthy2323d722021-02-12 22:55:38 -0800181 * Converts the stage-1 block attributes back to the corresponding mode.
182 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000183mm_mode_t arch_mm_stage1_attrs_to_mode(mm_attr_t attrs);
Raghu Krishnamurthy2323d722021-02-12 22:55:38 -0800184
185/**
Andrew Scullc280bee2019-08-14 11:11:03 +0100186 * Initializes the arch specific memory management.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000187 */
Karl Meakine1aeb1d2025-02-08 00:35:14 +0000188bool arch_mm_init(const struct mm_ptable *ptable);
Olivier Deprez96a2a262020-06-11 17:21:38 +0200189
190/**
191 * Return the arch specific mm mode for send/recv pages of given VM ID.
192 */
Karl Meakin07a69ab2025-02-07 14:53:19 +0000193mm_mode_t arch_mm_extra_mode_from_vm(ffa_id_t id);
Raghu Krishnamurthyc1012d62021-01-24 19:19:31 -0800194
195/**
196 * Execute any barriers or synchronization that is required
197 * by a given architecture, after page table writes.
198 */
199void arch_mm_sync_table_writes(void);
Federico Recanati4fd065d2021-12-13 20:06:23 +0100200
201/**
Jens Wiklander4f1880c2022-10-19 17:00:14 +0200202 * Returns the maximum supported PA Range index.
203 */
204uint64_t arch_mm_get_pa_range(void);
205
206/**
Federico Recanati4fd065d2021-12-13 20:06:23 +0100207 * Returns the maximum supported PA Range in bits.
208 */
Jens Wiklander4f1880c2022-10-19 17:00:14 +0200209uint32_t arch_mm_get_pa_bits(uint64_t pa_range);
Olivier Deprezb7f6bd62022-03-08 10:55:52 +0100210
Maksims Svecovs7efb1632022-03-29 17:05:24 +0100211/**
212 * Returns VTCR_EL2 configured in arch_mm_init.
213 */
Olivier Deprezb7f6bd62022-03-08 10:55:52 +0100214uintptr_t arch_mm_get_vtcr_el2(void);
215
Maksims Svecovs7efb1632022-03-29 17:05:24 +0100216/**
217 * Returns VSTCR_EL2 configured in arch_mm_init.
218 */
Olivier Deprezb7f6bd62022-03-08 10:55:52 +0100219uintptr_t arch_mm_get_vstcr_el2(void);