blob: e8d74edb525f2582746ee710eedd0ddc4edbbf4d [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
Andrew Scull11a4a0c2018-12-29 11:38:31 +000016/*
17 * A page table entry (PTE) will take one of the following forms:
Andrew Scullc66a04d2018-12-07 13:41:56 +000018 *
19 * 1. absent : There is no mapping.
20 * 2. invalid block : Represents a block that is not in the address space.
21 * 3. valid block : Represents a block that is in the address space.
22 * 4. table : Represents a reference to a table of PTEs.
23 */
Andrew Scull80871322018-08-06 12:04:09 +010024
Andrew Scull11a4a0c2018-12-29 11:38:31 +000025/**
26 * Creates an absent PTE.
Andrew Walbran25133742018-09-28 16:28:02 +010027 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000028pte_t arch_mm_absent_pte(uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000029
30/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000031 * Creates a table PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000032 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000033pte_t arch_mm_table_pte(uint8_t level, paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000034
35/**
36 * Creates a block PTE.
37 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000038pte_t arch_mm_block_pte(uint8_t level, paddr_t pa, uint64_t attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000039
40/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000041 * Checks whether a block is allowed at the given level of the page table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000042 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000043bool arch_mm_is_block_allowed(uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000044
45/**
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 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000049bool arch_mm_pte_is_present(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000050
51/**
52 * Determines if a PTE is valid i.e. it can affect the address space. Tables and
53 * valid blocks fall into this category. Invalid blocks do not as they hold
54 * information about blocks that are not in the address space.
55 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000056bool arch_mm_pte_is_valid(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000057
58/**
59 * Determines if a PTE is a block and represents an address range, valid or
60 * invalid.
61 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000062bool arch_mm_pte_is_block(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000063
64/**
65 * Determines if a PTE represents a reference to a table of PTEs.
66 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000067bool arch_mm_pte_is_table(pte_t pte, uint8_t level);
Andrew Scullc66a04d2018-12-07 13:41:56 +000068
Andrew Scull11a4a0c2018-12-29 11:38:31 +000069/**
70 * Clears the bits of an address that are ignored by the page table. In effect,
71 * the address is rounded down to the start of the corresponding PTE range.
72 */
Andrew Scull459d3b52018-12-07 16:37:12 +000073paddr_t arch_mm_clear_pa(paddr_t pa);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000074
75/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000076 * Extracts the start address of the PTE range.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000077 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000078paddr_t arch_mm_block_from_pte(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000079
80/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000081 * Extracts the address of the table referenced by the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000082 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000083paddr_t arch_mm_table_from_pte(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000084
85/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000086 * Extracts the attributes of the PTE.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000087 */
Andrew Scull3681b8d2018-12-12 14:22:59 +000088uint64_t arch_mm_pte_attrs(pte_t pte, uint8_t level);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000089
90/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000091 * Merges the attributes of a block into those of its containing table.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000092 */
Andrew Walbran2400ed22018-09-27 14:45:58 +010093uint64_t arch_mm_combine_table_entry_attrs(uint64_t table_attrs,
94 uint64_t block_attrs);
Andrew Scull11a4a0c2018-12-29 11:38:31 +000095
96/**
Andrew Scull9a6384b2019-01-02 12:08:40 +000097 * Invalidates the given range of stage-1 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +000098 */
Andrew Scull459d3b52018-12-07 16:37:12 +000099void arch_mm_invalidate_stage1_range(vaddr_t va_begin, vaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000100
101/**
Andrew Scull9a6384b2019-01-02 12:08:40 +0000102 * Invalidates the given range of stage-2 TLB.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000103 */
Andrew Scull459d3b52018-12-07 16:37:12 +0000104void arch_mm_invalidate_stage2_range(ipaddr_t va_begin, ipaddr_t va_end);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000105
106/**
Andrew Scullc059fbe2019-09-12 12:58:40 +0100107 * Writes back the given range of virtual memory to such a point that all cores
108 * and devices will see the updated values. The corresponding cache lines are
109 * also invalidated.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000110 */
Andrew Scullc059fbe2019-09-12 12:58:40 +0100111void arch_mm_flush_dcache(void *base, size_t size);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000112
113/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000114 * Gets the maximum level allowed in the page table for stage-1.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000115 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000116uint8_t arch_mm_stage1_max_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000117
118/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000119 * Gets the maximum level allowed in the page table for stage-2.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000120 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000121uint8_t arch_mm_stage2_max_level(void);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000122
123/**
Andrew Scullda3df7f2019-01-05 17:49:27 +0000124 * Gets the number of concatenated page tables used at the root for stage-1.
125 *
126 * Tables are concatenated at the root to avoid introducing another level in the
127 * page table meaning the table is shallow and wide. Each level is an extra
128 * memory access when walking the table so keeping it shallow reduces the memory
129 * accesses to aid performance.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000130 */
Andrew Scullda3df7f2019-01-05 17:49:27 +0000131uint8_t arch_mm_stage1_root_table_count(void);
132
133/**
134 * Gets the number of concatenated page tables used at the root for stage-2.
135 */
136uint8_t arch_mm_stage2_root_table_count(void);
137
138/**
139 * Converts the mode into stage-1 attributes for a block PTE.
140 */
Andrew Walbran1281ed42019-10-22 17:23:40 +0100141uint64_t arch_mm_mode_to_stage1_attrs(uint32_t mode);
Andrew Scullda3df7f2019-01-05 17:49:27 +0000142
143/**
144 * Converts the mode into stage-2 attributes for a block PTE.
145 */
Andrew Walbran1281ed42019-10-22 17:23:40 +0100146uint64_t arch_mm_mode_to_stage2_attrs(uint32_t mode);
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000147
148/**
Andrew Scull81e85092018-12-12 12:56:20 +0000149 * Converts the stage-2 block attributes back to the corresponding mode.
150 */
Andrew Walbran1281ed42019-10-22 17:23:40 +0100151uint32_t arch_mm_stage2_attrs_to_mode(uint64_t attrs);
Andrew Scull81e85092018-12-12 12:56:20 +0000152
153/**
Andrew Scullc280bee2019-08-14 11:11:03 +0100154 * Initializes the arch specific memory management.
Andrew Scull11a4a0c2018-12-29 11:38:31 +0000155 */
Andrew Scullb2910562019-09-17 14:08:27 +0100156bool arch_mm_init(paddr_t table);