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
|
#include "u.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "lib.h"
static int debug;
static uvlong by2pg; /* hwrpb->by2pg */
static uvlong pte2pg; /* by2pg/8 */
static uvlong pgmask; /* by2pg-1 */
static uvlong ptemask; /* pte2pg-1 */
static uvlong pgshift; /* log2(by2pg) */
static uvlong pteshift; /* log2(pte2pg) = pgshift - 3 */
#define L1(va) (((uvlong)(va)>>3*pteshift+3) & (pte2pg-1))
#define L2(va) (((uvlong)(va)>>2*pteshift+3) & (pte2pg-1))
#define L3(va) (((uvlong)(va)>>pgshift) & (pte2pg-1))
#define OFF(va) (((uvlong)(va)) & (by2pg-1))
#define V1(l1) (((vlong)l1<<(64-pteshift)) >> 64-(3*pteshift+3))
#define V2(l2) (((uvlong)l2<<(64-pteshift)) >> 64-(2*pteshift+3))
#define V3(l3) (((uvlong)l3<<(64-pteshift)) >> 64-pgshift)
#define VA(l1, l2, l3, off) (V1(l1) | V2(l2) | V3(l3) | (off))
static int
log2(uvlong x)
{
int i;
if ((x & (x-1)) == 0)
for (i = 0; i < 64; i++)
if (x & (1<<i))
return i;
panic("log2: %llux", x);
return -1;
}
void
mmuinit(void)
{
int i;
uvlong npage, nlvl2, nlvl3;
uvlong l1p, l2p, lvl2, lvl3;
extern ulong _main[], edata[];
/* map entire physical memory at KZERO */
by2pg = hwrpb->by2pg;
pte2pg = (by2pg >> 3);
pgmask = by2pg-1;
ptemask = pte2pg-1;
pgshift = log2(by2pg);
pteshift = pgshift-3;
l1p = (1LL<<3*pteshift+3)|(1LL<<2*pteshift+3)|(1LL<<pgshift);
if (rdv(l1p+8*(pte2pg-1)) != 0 || rdv(l1p+8*(pte2pg-2)) != 0)
panic("KZERO lvl1 already mapped");
npage = (conf.maxphys+pgmask)>>pgshift;
nlvl3 = (npage+ptemask)>>pteshift;
nlvl2 = (nlvl3+ptemask)>>pteshift;
if (nlvl2 > 1)
panic("meminit: nlvl2"); /* cannot happen, due to virtual space limitation */
if (debug)
print("nlvl1 %llud nlvl2 %llud nlvl3 %llud npage %llud\n", 1LL, nlvl2, nlvl3, npage);
lvl2 = allocate(nlvl2+nlvl3);
lvl3 = lvl2 + nlvl2*by2pg;
wrv(l1p+8*(pte2pg-2), rdv(l1p+8)|PTEASM);
wrv(l1p+8*(pte2pg-1), (lvl2<<(32-pgshift)) | PTEKVALID | PTEASM);
l2p = (1LL<<3*pteshift+3)|(1LL<<2*pteshift+3)|((vlong)KZERO >> 2*pteshift)&((1LL<<2*pteshift+3)-1);
for (i = 0; i < nlvl3; i++)
stqp(lvl2+(l2p&(by2pg-1))+8*i, ((lvl3+i*by2pg)<<(32-pgshift)) | PTEKVALID | PTEASM);
for (i = 0; i < npage; i++)
stqp(lvl3+8*i, ((uvlong)i<<32) | PTEKVALID | PTEASM);
tlbflush();
if (debug)
print("\n");
}
uvlong
paddr(uvlong va)
{
uvlong ptbr, x, pte;
ptbr = getptbr();
pte = ldqp((ptbr<<pgshift)+8*L1(va));
if ((pte&PTEKVALID) != PTEKVALID)
return 0;
x = ((pte>>32)<<pgshift);
pte = ldqp(x+8*L2(va));
if ((pte&PTEKVALID) != PTEKVALID)
return 0;
x = ((pte>>32)<<pgshift);
pte = ldqp(x+8*L3(va));
if ((pte&PTEKVALID) != PTEKVALID)
return 0;
x = ((pte>>32)<<pgshift);
return x;
}
uvlong
pground(uvlong x)
{
return (x+pgmask) & ~pgmask;
}
|