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
|
static uint64_t translate(uint64_t va)
{
uint64_t par, el;
asm volatile("mrs %0, CurrentEL" : "=r" (el));
el >>= 2;
if (el == 2)
asm volatile(
"at s1e2r, %1\n"
"isb\n"
"mrs %0, par_el1\n"
: "=r" (par)
: "r" (va)
: "memory");
else
asm volatile(
"at s1e1r, %1\n"
"isb\n"
"mrs %0, par_el1\n"
: "=r" (par)
: "r" (va)
: "memory");
return par;
}
static int check(const char *name, uint64_t va)
{
uint64_t par = translate(va);
if (par & PAR_F) {
dprintf(ALWAYS, "mmu: %s faulted (par 0x%016llx)\n",
name, (unsigned long long)par);
return 1;
}
if ((par & PAR_PA_MASK) != (va & PAR_PA_MASK)) {
dprintf(ALWAYS, "mmu: %s pa %llx != va %llx\n",
name, (unsigned long long)(par & PAR_PA_MASK),
(unsigned long long)va);
return 1;
}
dprintf(ALWAYS, "mmu: %s ok, pa %llx\n",
name, (unsigned long long)(par & PAR_PA_MASK));
return 0;
}
int tb_mmu_selftest(void)
{
int ret = 0;
ret |= check("mmio 0x09000000 (uart)", 0x09000000);
ret |= check("mmio 0x00000000", 0x00000000);
ret |= check("ram 0x40200000 (load)", 0x40200000);
ret |= check("ram 0x41000000", 0x41000000);
ret |= check("self 0x40080000 (stack guard region, no map)",
0x40080000);
return ret;
}
|