/
translationtable.cpp
121 lines (104 loc) · 3.51 KB
/
translationtable.cpp
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
//
// translationtable.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2016-2017 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <circle/translationtable.h>
#include <circle/synchronize.h>
#include <circle/sysconfig.h>
#include <circle/alloc.h>
#include <circle/util.h>
#include <assert.h>
// Granule size is 64KB. Only EL1 stage 1 translation is enabled with 32 bits IPA (= PA) size (4GB).
// We create one level 2 (first lookup level) translation table with 3 table entries (total 1.5GB) which
// point to a level 3 (final lookup level) translation table each with 8192 page entries a 64KB (total 512MB).
CTranslationTable::CTranslationTable (u64 nMemSize)
: m_nMemSize (nMemSize),
m_pTable (0)
{
m_pTable = (TARMV8MMU_LEVEL2_DESCRIPTOR *) palloc ();
assert (m_pTable != 0);
memset (m_pTable, 0, PAGE_SIZE);
for (unsigned nEntry = 0; nEntry < 3; nEntry++) // 3 entries a 512MB
{
u64 nBaseAddress = (u64) nEntry * ARMV8MMU_TABLE_ENTRIES * ARMV8MMU_LEVEL3_PAGE_SIZE;
TARMV8MMU_LEVEL3_DESCRIPTOR *pTable = CreateLevel3Table (nBaseAddress);
assert (pTable != 0);
TARMV8MMU_LEVEL2_TABLE_DESCRIPTOR *pDesc = &m_pTable[nEntry].Table;
pDesc->Value11 = 3;
pDesc->Ignored1 = 0;
pDesc->TableAddress = ARMV8MMUL2TABLEADDR ((u64) pTable);
pDesc->Reserved0 = 0;
pDesc->Ignored2 = 0;
pDesc->PXNTable = 0;
pDesc->UXNTable = 0;
pDesc->APTable = AP_TABLE_ALL_ACCESS;
pDesc->NSTable = 0;
}
DataSyncBarrier ();
}
CTranslationTable::~CTranslationTable (void)
{
pfree (m_pTable);
m_pTable = 0;
}
u64 CTranslationTable::GetBaseAddress (void) const
{
assert (m_pTable != 0);
return (u64) m_pTable;
}
TARMV8MMU_LEVEL3_DESCRIPTOR *CTranslationTable::CreateLevel3Table (u64 nBaseAddress)
{
TARMV8MMU_LEVEL3_DESCRIPTOR *pTable = (TARMV8MMU_LEVEL3_DESCRIPTOR *) palloc ();
assert (pTable != 0);
for (unsigned nPage = 0; nPage < ARMV8MMU_TABLE_ENTRIES; nPage++) // 8192 entries a 64KB
{
TARMV8MMU_LEVEL3_PAGE_DESCRIPTOR *pDesc = &pTable[nPage].Page;
pDesc->Value11 = 3;
pDesc->AttrIndx = ATTRINDX_NORMAL;
pDesc->NS = 0;
pDesc->AP = ATTRIB_AP_RW_EL1;
pDesc->SH = ATTRIB_SH_INNER_SHAREABLE;
pDesc->AF = 1;
pDesc->nG = 0;
pDesc->Reserved0_1 = 0;
pDesc->OutputAddress = ARMV8MMUL3PAGEADDR (nBaseAddress);
pDesc->Reserved0_2 = 0;
pDesc->Continous = 0;
pDesc->PXN = 0;
pDesc->UXN = 1;
pDesc->Ignored = 0;
extern u8 _etext;
if (nBaseAddress >= (u64) &_etext)
{
pDesc->PXN = 1;
if (nBaseAddress >= m_nMemSize)
{
pDesc->AttrIndx = ATTRINDX_DEVICE;
pDesc->SH = ATTRIB_SH_OUTER_SHAREABLE;
}
else if ( nBaseAddress >= MEM_COHERENT_REGION
&& nBaseAddress < MEM_HEAP_START)
{
pDesc->AttrIndx = ATTRINDX_COHERENT;
pDesc->SH = ATTRIB_SH_OUTER_SHAREABLE;
}
}
nBaseAddress += ARMV8MMU_LEVEL3_PAGE_SIZE;
}
return pTable;
}