blob: ed7d69040a0120bac712ab5945fcb414777f9412 [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
11#include <stdbool.h>
12#include <stddef.h>
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010013
Andrew Scull18c78fc2018-08-20 12:57:41 +010014#include "hf/addr.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 * A page table entry (PTE) will take one of the following forms:
Andrew Scullc66a04d2018-12-07 13:41:56 +000020 *
21 * 1. absent : There is no mapping.
22 * 2. invalid block : Represents a block that is not in the address space.
23 * 3. valid block : Represents a block that is in the address space.
24 * 4. table : Represents a reference to a table of PTEs.
25 */
Andrew Scull80871322018-08-06 12:04:09 +010026
Andrew Scull11a4a0c2018-12-29 11:38:31 +000027/**
28 * Creates an absent PTE.
Andrew Walbran25133742018-09-28 16:28:02 +010029 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000030pte_t arch_mm_absent_pte(uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000031
32/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000033 * Creates a table PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000034 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000035pte_t arch_mm_table_pte(uint8_t level, paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000036
37/**
38 * Creates a block PTE.
39 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000040pte_t arch_mm_block_pte(uint8_t level, paddr_t pa, uint64_t attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000041
42/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000043 * Checks whether a block is allowed at the given level of the page table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000044 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000045bool arch_mm_is_block_allowed(uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000046
47/**
48 * Determines if a PTE is present i.e. it contains information and therefore
49 * needs to exist in the page table. Any non-absent PTE is present.
50 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000051bool arch_mm_pte_is_present(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000052
53/**
54 * Determines if a PTE is valid i.e. it can affect the address space. Tables and
55 * valid blocks fall into this category. Invalid blocks do not as they hold
56 * information about blocks that are not in the address space.
57 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000058bool arch_mm_pte_is_valid(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000059
60/**
61 * Determines if a PTE is a block and represents an address range, valid or
62 * invalid.
63 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000064bool arch_mm_pte_is_block(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000065
66/**
67 * Determines if a PTE represents a reference to a table of PTEs.
68 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000069bool arch_mm_pte_is_table(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000070
Andrew Scull11a4a0c2018-12-29 11:38:31 +000071/**
72 * Clears the bits of an address that are ignored by the page table. In effect,
73 * the address is rounded down to the start of the corresponding PTE range.
74 */
Andrew Scull459d3b52018-12-07 16:37:12 +000075paddr_t arch_mm_clear_pa(paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000076
77/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000078 * Extracts the start address of the PTE range.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000079 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000080paddr_t arch_mm_block_from_pte(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000081
82/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000083 * Extracts the address of the table referenced by the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000084 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000085paddr_t arch_mm_table_from_pte(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000086
87/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000088 * Extracts the attributes of the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000089 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000090uint64_t arch_mm_pte_attrs(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000091
92/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000093 * Merges the attributes of a block into those of its containing table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000094 */
Andrew Walbran2400ed22018-09-27 14:45:58 +010095uint64_t arch_mm_combine_table_entry_attrs(uint64_t table_attrs,
96 uint64_t block_attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000097
98/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000099 * Invalidates the given range of stage-1 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000100 */
Raghu Krishnamurthy8fdd6df2021-02-03 18:30:59 -0800101void arch_mm_invalidate_stage1_range(uint16_t asid, vaddr_t va_begin,
102 vaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000103
104/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000105 * Invalidates the given range of stage-2 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000106 */
Raghu Krishnamurthy8fdd6df2021-02-03 18:30:59 -0800107void arch_mm_invalidate_stage2_range(uint16_t vmid, ipaddr_t va_begin,
108 ipaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000109
110/**
Andrew Scullc059fbe2019-09-12 12:58:40 +0100111 * Writes back the given range of virtual memory to such a point that all cores
112 * and devices will see the updated values. The corresponding cache lines are
113 * also invalidated.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000114 */
Andrew Scullc059fbe2019-09-12 12:58:40 +0100115void arch_mm_flush_dcache(void *base, size_t size);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000116
117/**
Arunachalam Ganapathy0f0f7062022-01-26 17:09:53 +0000118 * Sets the maximum level allowed in the page table for stage-1.
119 */
120void arch_mm_stage1_max_level_set(uint32_t pa_bits);
121
122/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000123 * Gets the maximum level allowed in the page table for stage-1.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000124 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000125uint8_t arch_mm_stage1_max_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000126
127/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000128 * Gets the maximum level allowed in the page table for stage-2.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000129 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000130uint8_t arch_mm_stage2_max_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000131
132/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000133 * Gets the number of concatenated page tables used at the root for stage-1.
134 *
135 * Tables are concatenated at the root to avoid introducing another level in the
136 * page table meaning the table is shallow and wide. Each level is an extra
137 * memory access when walking the table so keeping it shallow reduces the memory
138 * accesses to aid performance.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000139 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000140uint8_t arch_mm_stage1_root_table_count(void);
141
142/**
143 * Gets the number of concatenated page tables used at the root for stage-2.
144 */
145uint8_t arch_mm_stage2_root_table_count(void);
146
147/**
148 * Converts the mode into stage-1 attributes for a block PTE.
149 */
Andrew Walbran1281ed42019-10-22 17:23:40 +0100150uint64_t arch_mm_mode_to_stage1_attrs(uint32_t mode);
Andrew Scullda3df7f2019-01-05 17:49:27 +0000151
152/**
153 * Converts the mode into stage-2 attributes for a block PTE.
154 */
Andrew Walbran1281ed42019-10-22 17:23:40 +0100155uint64_t arch_mm_mode_to_stage2_attrs(uint32_t mode);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000156
157/**
Andrew Scull81e85092018-12-12 12:56:20 +0000158 * Converts the stage-2 block attributes back to the corresponding mode.
159 */
Andrew Walbran1281ed42019-10-22 17:23:40 +0100160uint32_t arch_mm_stage2_attrs_to_mode(uint64_t attrs);
Andrew Scull81e85092018-12-12 12:56:20 +0000161
162/**
Raghu Krishnamurthy2323d722021-02-12 22:55:38 -0800163 * Converts the stage-1 block attributes back to the corresponding mode.
164 */
165uint32_t arch_mm_stage1_attrs_to_mode(uint64_t attrs);
166
167/**
Andrew Scullc280bee2019-08-14 11:11:03 +0100168 * Initializes the arch specific memory management.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000169 */
Andrew Scullb2910562019-09-17 14:08:27 +0100170bool arch_mm_init(paddr_t table);
Olivier Deprez96a2a262020-06-11 17:21:38 +0200171
172/**
173 * Return the arch specific mm mode for send/recv pages of given VM ID.
174 */
175uint32_t arch_mm_extra_attributes_from_vm(ffa_vm_id_t id);
Raghu Krishnamurthyc1012d62021-01-24 19:19:31 -0800176
177/**
178 * Execute any barriers or synchronization that is required
179 * by a given architecture, after page table writes.
180 */
181void arch_mm_sync_table_writes(void);
Federico Recanati4fd065d2021-12-13 20:06:23 +0100182
183/**
Jens Wiklander4f1880c2022-10-19 17:00:14 +0200184 * Returns the maximum supported PA Range index.
185 */
186uint64_t arch_mm_get_pa_range(void);
187
188/**
Federico Recanati4fd065d2021-12-13 20:06:23 +0100189 * Returns the maximum supported PA Range in bits.
190 */
Jens Wiklander4f1880c2022-10-19 17:00:14 +0200191uint32_t arch_mm_get_pa_bits(uint64_t pa_range);
Olivier Deprezb7f6bd62022-03-08 10:55:52 +0100192
Maksims Svecovs7efb1632022-03-29 17:05:24 +0100193/**
194 * Returns VTCR_EL2 configured in arch_mm_init.
195 */
Olivier Deprezb7f6bd62022-03-08 10:55:52 +0100196uintptr_t arch_mm_get_vtcr_el2(void);
197
Maksims Svecovs7efb1632022-03-29 17:05:24 +0100198/**
199 * Returns VSTCR_EL2 configured in arch_mm_init.
200 */
Olivier Deprezb7f6bd62022-03-08 10:55:52 +0100201uintptr_t arch_mm_get_vstcr_el2(void);