-
Notifications
You must be signed in to change notification settings - Fork 0
/
page.cpp
131 lines (111 loc) · 3.21 KB
/
page.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
122
123
124
125
126
127
128
129
130
131
#include "os.hh"
#include <cassert>
/**
* Following global variables defined in mem.S
*/
extern uint32_t TEXT_START;
extern uint32_t TEXT_END;
extern uint32_t DATA_START;
extern uint32_t DATA_END;
extern uint32_t RODATA_START;
extern uint32_t RODATA_END;
extern uint32_t BSS_START;
extern uint32_t BSS_END;
extern uint32_t HEAP_START;
extern uint32_t HEAP_SIZE;
#define PAGE_SIZE 4096
#define PAGE_ALIGN 12
#define PAGE_TAKEN (uint8_t)(1 << 0)
#define PAGE_LAST (uint8_t)(1 << 1)
void MemoryManager::InitPage() {
m_num_pages = (HEAP_SIZE / PAGE_SIZE) - 8;
printf("HEAP_START = 0x%x, HEAP_SIZE = 0x%x, num of pages = %ld\n", HEAP_START, HEAP_SIZE, m_num_pages);
Page *page = (Page *) HEAP_START;
for (uint32_t i = 0; i < m_num_pages; ++i) {
Clear(page);
++page;
}
m_alloc_start = AlignPage(HEAP_START + 8 * PAGE_SIZE);
m_alloc_end = m_alloc_start + (PAGE_SIZE * m_num_pages);
printf("TEXT: 0x%x -> 0x%x\n", TEXT_START, TEXT_END);
printf("RODATA: 0x%x -> 0x%x\n", RODATA_START, RODATA_END);
printf("DATA: 0x%x -> 0x%x\n", DATA_START, DATA_END);
printf("BSS: 0x%x -> 0x%x\n", BSS_START, BSS_END);
printf("HEAP: 0x%x -> 0x%x\n", m_alloc_start, m_alloc_end);
}
/**
* Allocate a memory block which is composed of continuous physical pages.
* TODO(zhong): Optimize by a new algorithm.
* @param npages: Page number to allocate.
*/
void *MemoryManager::AllocPage(uint32_t npages) {
bool found = false;
Page *search_page = (Page *) HEAP_START;
for (uint32_t i = 0; i < m_num_pages - npages; ++i) {
if (IsFree(search_page)) {
found = true;
Page *page_start = search_page + 1;
// Find enough continuous pages
uint32_t j = i + 1;
for (; j < (i + npages); ++j) {
if (!IsFree(page_start)) {
found = false;
break;
}
++page_start;
}
// Mark flag if found
if (found) {
Page *page_target = search_page;
for (uint32_t k = i; k < (i + npages); ++k) {
SetFlag(page_target, PAGE_TAKEN);
++page_target;
}
--page_target;
SetFlag(page_target, PAGE_LAST);
return (void *) (m_alloc_start + i * PAGE_SIZE);
}
}
++search_page;
}
return nullptr;
}
void MemoryManager::FreePage(void *p) {
if (!p || (uint64_t) p > m_alloc_end) {
return;
}
Page *page = (Page *) HEAP_START;
page += ((uint64_t) p - m_alloc_start) / PAGE_SIZE;
// Loop and clear allocated pages
while (!IsFree(page)) {
Clear(page);
if (IsLast(page)) break;
else ++page;
}
}
void MemoryManager::Clear(Page *page) {
page->flags = 0;
}
bool MemoryManager::IsFree(Page *page) {
return !(page->flags & PAGE_TAKEN);
}
void MemoryManager::SetFlag(Page *page, uint8_t flags) {
page->flags |= flags;
}
bool MemoryManager::IsLast(Page *page) {
return page->flags & PAGE_LAST;
}
uint32_t MemoryManager::AlignPage(uint32_t address) {
uint32_t align = (1 << PAGE_ALIGN) - 1;
return (address + align) & (~align);
}
void MemoryManager::PageTest() {
void *p = AllocPage(2);
printf("p = 0x%x\n", p);
printf("p = 0x%x\n", (uint64_t) p >> 32);
void *p2 = AllocPage(7);
printf("p2 = 0x%x\n", p2);
FreePage(p2);
void *p3 = AllocPage(4);
printf("p3 = 0x%x\n", p3);
}