-
Notifications
You must be signed in to change notification settings - Fork 0
/
friend042.cc
138 lines (109 loc) · 4.13 KB
/
friend042.cc
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
#include "app.h"
#include "common.h"
void show_i(F2H &f2h, int i) {
char mes[] = "i=0";
mes[2] += i;
puts(f2h, mes);
}
/*どの程度メモリが使用されているかを検知することができればメモリ管理ができるのでは?
参考: Ingensでは100%(2MB)以外ヒュージページ化していない
つまり、0xC0000000もしくは0xC0200000からの2MBが使用されていたらヒュージページ化するということ?
例: pd2[1] = pd2[1] | (1 << 7);
*/
void create_pagetable(uint64_t *page_structures, uint64_t *pd_for_baremetal,
uint64_t page_for_app) {
// how to use 16KB
// 0-4KB: PML4T
// 4KB-8KB: PDPT
// 8KB-12KB: PD
// 12KB-16KB: PT
uint64_t *pml4t = page_structures;
uint64_t *pdpt = (uint64_t *)((uint64_t)page_structures + 0x1000);
uint64_t *pd = (uint64_t *)((uint64_t)page_structures + 0x2000);
uint64_t *pt = (uint64_t *)((uint64_t)page_structures + 0x3000);
pml4t[0] = ((uint64_t)pdpt + 0x80000000UL) | (1 << 0) | (1 << 1) | (1 << 2);
pdpt[0] = ((uint64_t)pd_for_baremetal + 0x80000000UL) | (1 << 0) | (1 << 1) |
(1 << 2);
pdpt[3] = ((uint64_t)pd + 0x80000000UL) | (1 << 0) | (1 << 1) | (1 << 2);
pd[0] = ((uint64_t)pt + 0x80000000UL) | (1 << 0) | (1 << 1) | (1 << 2);
pt[0] = page_for_app | (1 << 0) | (1 << 1) | (1 << 2);
}
void map_page(uint64_t *page_structures) {
uint64_t *pt = (uint64_t *)((uint64_t)page_structures + 0x3000);
pt[1] = 0x80700000UL | (1 << 0) | (1 << 1) | (1 << 2);
asm volatile("invlpg (%0)" ::"b"(0xC0000000UL) : "memory");
}
void unmap_page(uint64_t *page_structures) {
uint64_t *pt = (uint64_t *)((uint64_t)page_structures + 0x3000);
pt[1] = 0;
asm volatile("invlpg (%0)" ::"b"(0xC0000000UL) : "memory");
}
int main() {
F2H f2h;
puts(f2h, "hello!");
memset((void *)0x310000UL, 0, 0x9000);
uint64_t *page_structures_for_app1 =
(uint64_t *)0x310000UL; // 16KB (for PML4T, PDPT, PD, PT)
uint64_t *page_structures_for_app2 =
(uint64_t *)0x314000UL; // 16KB (for PML4T, PDPT, PD, PT)
uint64_t *pd_for_baremetal = (uint64_t *)0x318000UL;
// page directory of virtual address 0 - 1GB (for friend.cc)
// shared by app1 and app2
for (int i = 0; i < 512; i++) {
pd_for_baremetal[i] = (0x80000000UL + 0x200000UL * i) | (1 << 0) |
(1 << 1) | (1 << 2) | (1 << 7) | (1 << 8);
}
create_pagetable(page_structures_for_app1, pd_for_baremetal, 0x80500000UL);
create_pagetable(page_structures_for_app2, pd_for_baremetal, 0x80600000UL);
uint64_t *pml4t_for_app1 = page_structures_for_app1;
uint64_t *pml4t_for_app2 = page_structures_for_app2;
extern uint8_t _binary_app1_start[];
extern uint8_t _binary_app1_size[];
extern uint8_t _binary_app2_start[];
extern uint8_t _binary_app2_size[];
memcpy((void *)0x500000UL, (const void *)_binary_app1_start,
(size_t)_binary_app1_size);
memcpy((void *)0x600000UL, (const void *)_binary_app2_start,
(size_t)_binary_app2_size);
Context c1;
c1.next = (Context(*)(Context))0xC0000000UL; // entry1
c1.i = 0;
asm volatile("movq %0, %%cr3" ::"r"((uint64_t)pml4t_for_app1 + 0x80000000UL));
map_page(page_structures_for_app1);
c1 = c1.next(c1); // call entry1
unmap_page(page_structures_for_app1);
show_i(f2h, c1.i);
if (c1.i != 1) {
return_value(f2h, 1);
return 1;
}
Context c2;
c2.next = (Context(*)(Context))0xC0000000UL; // entry3
c2.i = 0;
asm volatile("movq %0, %%cr3" ::"r"((uint64_t)pml4t_for_app2 + 0x80000000UL));
c2 = c2.next(c2); // call entry3
show_i(f2h, c2.i);
if (c2.i != 9) {
return_value(f2h, 1);
return 1;
}
asm volatile("movq %0, %%cr3" ::"r"((uint64_t)pml4t_for_app1 + 0x80000000UL));
c1 = c1.next(c1); // call entry2
show_i(f2h, c1.i);
if (c1.i != 2) {
return_value(f2h, 1);
return 1;
}
asm volatile("movq %0, %%cr3" ::"r"((uint64_t)pml4t_for_app2 + 0x80000000UL));
map_page(page_structures_for_app2);
c2 = c2.next(c2); // call entry4
unmap_page(page_structures_for_app2);
show_i(f2h, c2.i);
if (c2.i != 8) {
return_value(f2h, 1);
return 1;
}
puts(f2h, "bye!");
return_value(f2h, 0);
return 0;
}