/
memory.hpp
139 lines (113 loc) · 6.54 KB
/
memory.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
Copyright (c) 2023, Thierry Tremblay
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <cstdint>
namespace mtl
{
/*
AArch64 Page Mapping Overview
Table with 4K
Page Table Level Bits ARM Name
---------------------------------------------------------------------------------------------------
4 9 bits Level 0 table (512 GB / entry)
3 9 bits Level 1 table (1 GB / entry)
2 9 bits Level 2 table (2 MB / entry)
1 9 bits Level 3 table (4 KB / entry)
(page) 12 bits Page
---------------------------------------------------------------------------------------------------
48 bits Virtual address size
48 bits Physical address size
256 TB Addressable Physical Memory
Reference:
https://medium.com/@om.nara/arm64-normal-memory-attributes-6086012fa0e3
https://developer.arm.com/documentation/101811/0102/Address-spaces
https://developer.arm.com/documentation/101811/0102/Controlling-address-translation-Translation-table-format
*/
using PhysicalAddress = uint64_t;
// Normal pages are 4 KB
static constexpr auto kMemoryPageShift = 12;
static constexpr auto kMemoryPageSize = 4096;
// Large pages are 2 MB
static constexpr auto kMemoryLargePageShift = 21;
static constexpr auto kMemoryLargePageSize = 2 * 1024 * 1024;
// Huge pages are 1 GB
static constexpr auto kMemoryHugePageShift = 30;
static constexpr auto kMemoryHugePageSize = 1024 * 1024 * 1024;
enum PageFlags : uint64_t
{
Valid = 1 << 0, // Descriptor is valid
Table = 1 << 1, // Entry is a page table
Page = 1 << 1, // Entry is a page (same as Table, ugh)
MAIR = 7 << 2, // Index into the MAIR_ELn (similar to x86 PATs)
NS = 1 << 5, // Security bit, but only at EL3 and Secure EL1
AP1 = 1 << 6, // EL0 (user) access (aka PAGE_USER on x86)
AP2 = 1 << 7, // Read only (opposite of PAGE_WRITE on x86)
OuterShareable = 2 << 8, // Outer Shareable
InnerShareable = 3 << 8, // Inner Shareable
AccessFlag = 1 << 10, // Access flag (if 0, will trigger a page fault)
// Memory Attribute Indirection Register (MAIR)
// These happen to match what UEFI configures
Uncacheable = 0 << 2, // MAIR index 0
WriteCombining = 1 << 2, // MAIR index 1
WriteThrough = 2 << 2, // MAIR index 2
WriteBack = 3 << 2, // MAIR index 3
MAIR_4 = 4 << 2, // MAIR index 4
MAIR_5 = 5 << 2, // MAIR index 5
MAIR_6 = 6 << 2, // MAIR index 6
MAIR_7 = 7 << 2, // MAIR index 7
// Bits 12..47 are the address mask
AddressMask = 0x0000FFFFFFFFF000ull,
// Bits 51..48 are reserved
DirtyBitModifier = 1ull << 51, // Dirty Bit Modifier
Contiguous = 1ull << 52, // Optimization to efficiently use TLB space
PXN = 1ull << 53, // Privileged eXecute Never
UXN = 1ull << 54, // Unprivileged eXecute Never
// bits 55-58 are reserved for software use
// https://medium.com/@om.nara/arm64-normal-memory-attributes-6086012fa0e3
PXNTable = 1ull << 59, // Privileged eXecute Never
UXNTable = 1ull << 60, // Unprivileged eXecute Never
APTableMask = 3ull << 61, // Access Permission limits for subsequent levels of lookup
NSTable = 1ull << 63, // (0 - Secure PA space, 1 - Non-Secure)
// Aliases
User = AP1, // Accessible to user space
ReadOnly = AP2, // Read-only
FlagsMask = ~AddressMask & ~DirtyBitModifier,
// Page types
PageTable = Valid | Table | AccessFlag | WriteBack,
KernelCode = Valid | Page | InnerShareable | AccessFlag | UXN | ReadOnly | WriteBack,
KernelData_RO = Valid | Page | InnerShareable | AccessFlag | UXN | PXN | ReadOnly | WriteBack,
KernelData_RW = Valid | Page | InnerShareable | AccessFlag | UXN | PXN | WriteBack,
UserCode = Valid | Page | InnerShareable | AccessFlag | User | ReadOnly | WriteBack,
UserData_RO = Valid | Page | InnerShareable | AccessFlag | UXN | PXN | User | ReadOnly | WriteBack,
UserData_RW = Valid | Page | InnerShareable | AccessFlag | UXN | PXN | User | WriteBack,
MMIO = Valid | Page | AccessFlag | UXN | PXN | Uncacheable,
VideoFrameBuffer = Valid | Page | AccessFlag | UXN | PXN | WriteCombining,
};
// MAIR Memory Types
enum Mair : uint64_t
{
MairUncacheable = 0x00, // Device-nGnRnE (Device non-Gathering, non-Reordering, no Early Write Acknowledgement)
MairWriteCombining = 0x44, // Normal Memory, Outer non-cacheable, Inner non-cacheable
MairWriteThrough = 0xbb, // Normal Memory, Outer Write-through non-transient, Inner Write-through non-transient
MairWriteBack = 0xff, // Normal Memory, Outer Write-back non-transient, Inner Write-back non-transient
};
} // namespace mtl