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
|
#ifndef __KERNEL_VMMMGR_H
#define __KERNEL_VMMMGR_H
#include <kernel/types.h>
class VmmManager
{
public:
struct pte_t
{
uint64_t a,b;
};
enum VMM_CONSTS
{
FULL_MEM_SIZE = 8 * 1024 * 1024,
PAGESIZE = 4096,
PTSIZE = (1 << 18),
PTEG_SIZE = 8,
PTEG_COUNT = (PTSIZE / sizeof(pte_t)) / PTEG_SIZE,
HTABORG = (FULL_MEM_SIZE - PTSIZE),
};
enum ACCESS_TYPES
{
NO_USER_ACCESS,
NORMAL_ACCESS,
CI_ACCESS,
};
enum PID_ALLOCATIONS
{
LinearSpace = 0,
MMIOSpace = 1,
FirstPid,
};
static void init();
protected:
VmmManager();
~VmmManager() {};
private:
void initSLB();
void initPTEs();
void initSDR1();
static pte_t* page_table;
inline pte_t& getPte(uint64_t pteg, uint64_t idx)
{
return page_table[pteg * PTEG_SIZE + idx];
}
inline void defaultPte(pte_t& pte)
{
pte.a = 0x4000000000000000; // B = 01 (1TB).
pte.b = 0x0;
}
inline void setValid(bool valid, pte_t& pte)
{
// Adding a page requires EIEIO to ensure update of PTE prior
// to making valid and PTESYNC afterwards.
// Removing a page just requires PTESYNC afterwards.
if (valid)
{
asm volatile("eieio" ::: "memory");
}
pte.a &= ~0x01;
pte.a |= (valid ? 0x1 : 0x0);
asm volatile("ptesync" ::: "memory");
}
inline bool isValid(pte_t& pte)
{
return ((pte.a & 0x01) == 0x01);
}
inline void setTid(tid_t tid, pte_t& pte)
{
pte.a &= 0xC00000000000007F;
pte.a |= ((uint64_t) tid) << 7;
}
inline tid_t getTid(pte_t& pte)
{
return (tid_t) ((pte.a & 0xC00000000000007F) >> 7);
}
inline void setAccess(ACCESS_TYPES t, pte_t& pte)
{
uint64_t pteMask = ~0x800000000000007B;
pte.b &= pteMask;
pte.b |= (NO_USER_ACCESS == t ? 0x0000000000000010 :
(NORMAL_ACCESS == t ? 0x0000000000000012 :
(CI_ACCESS == t ? 0x000000000000002A :
0x0)));
}
inline void setPage(uint64_t page, pte_t& pte)
{
pte.b &= ~0x0FFFFFFFFFFFF000;
pte.b |= page << 12;
}
inline uint64_t getPage(pte_t& pte)
{
return (pte.b & 0x0FFFFFFFFFFFF000) >> 12;
}
inline void pteSync()
{
asm volatile("ptesync" ::: "memory");
}
};
#endif
|