-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboot.c
175 lines (138 loc) · 4.49 KB
/
boot.c
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <asm/csr.h>
#include "printf.h"
#include "interrupt.h"
#include "syscall.h"
#include "vm.h"
#include "string.h"
#include "sbi.h"
#include "freemem.h"
#include "mm.h"
#include "env.h"
#include "paging.h"
/* defined in vm.h */
extern uintptr_t shared_buffer;
extern uintptr_t shared_buffer_size;
/* initial memory layout */
uintptr_t utm_base;
size_t utm_size;
/* defined in entry.S */
extern void* encl_trap_handler;
#ifdef USE_FREEMEM
/* map entire enclave physical memory so that
* we can access the old page table and free memory */
/* remap runtime kernel to a new root page table */
void
map_physical_memory(uintptr_t dram_base,
uintptr_t dram_size)
{
uintptr_t ptr = EYRIE_LOAD_START;
/* load address should not override kernel address */
assert(RISCV_GET_PT_INDEX(ptr, 1) != RISCV_GET_PT_INDEX(runtime_va_start, 1));
map_with_reserved_page_table(dram_base, dram_size,
ptr, load_l2_page_table, load_l3_page_table);
}
void
remap_kernel_space(uintptr_t runtime_base,
uintptr_t runtime_size)
{
/* eyrie runtime is supposed to be smaller than a megapage */
#if __riscv_xlen == 64
assert(runtime_size <= RISCV_GET_LVL_PGSIZE(2));
#elif __riscv_xlen == 32
assert(runtime_size <= RISCV_GET_LVL_PGSIZE(1));
#endif
map_with_reserved_page_table(runtime_base, runtime_size,
runtime_va_start, kernel_l2_page_table, kernel_l3_page_table);
}
void
copy_root_page_table()
{
/* the old table lives in the first page */
pte* old_root_page_table = (pte*) EYRIE_LOAD_START;
int i;
/* copy all valid entries of the old root page table */
for (i = 0; i < BIT(RISCV_PT_INDEX_BITS); i++) {
if (old_root_page_table[i] & PTE_V &&
!(root_page_table[i] & PTE_V)) {
root_page_table[i] = old_root_page_table[i];
}
}
}
/* initialize free memory with a simple page allocator*/
void
init_freemem()
{
spa_init(freemem_va_start, freemem_size);
}
#endif // USE_FREEMEM
/* initialize user stack */
void
init_user_stack_and_env()
{
void* user_sp = (void*) EYRIE_USER_STACK_START;
#ifdef USE_FREEMEM
size_t count;
uintptr_t stack_end = EYRIE_USER_STACK_END;
size_t stack_count = EYRIE_USER_STACK_SIZE >> RISCV_PAGE_BITS;
// allocated stack pages right below the runtime
count = alloc_pages(vpn(stack_end), stack_count,
PTE_R | PTE_W | PTE_D | PTE_A | PTE_U);
assert(count == stack_count);
#endif // USE_FREEMEM
// setup user stack env/aux
user_sp = setup_start(user_sp);
// prepare user sp
csr_write(sscratch, user_sp);
}
void
eyrie_boot(uintptr_t dummy, // $a0 contains the return value from the SBI
uintptr_t dram_base,
uintptr_t dram_size,
uintptr_t runtime_paddr,
uintptr_t user_paddr,
uintptr_t free_paddr,
uintptr_t utm_vaddr,
uintptr_t utm_size)
{
/* set initial values */
load_pa_start = dram_base;
shared_buffer = utm_vaddr;
shared_buffer_size = utm_size;
runtime_va_start = (uintptr_t) &rt_base;
kernel_offset = runtime_va_start - runtime_paddr;
debug("UTM : 0x%lx-0x%lx (%u KB)", utm_vaddr, utm_vaddr+utm_size, utm_size/1024);
debug("DRAM: 0x%lx-0x%lx (%u KB)", dram_base, dram_base + dram_size, dram_size/1024);
#ifdef USE_FREEMEM
freemem_va_start = __va(free_paddr);
freemem_size = dram_base + dram_size - free_paddr;
debug("FREE: 0x%lx-0x%lx (%u KB), va 0x%lx", free_paddr, dram_base + dram_size, freemem_size/1024, freemem_va_start);
/* remap kernel VA */
remap_kernel_space(runtime_paddr, user_paddr - runtime_paddr);
map_physical_memory(dram_base, dram_size);
/* switch to the new page table */
csr_write(satp, satp_new(kernel_va_to_pa(root_page_table)));
/* copy valid entries from the old page table */
copy_root_page_table();
/* initialize free memory */
init_freemem();
//TODO: This should be set by walking the userspace vm and finding
//highest used addr. Instead we start partway through the anon space
set_program_break(EYRIE_ANON_REGION_START + (1024 * 1024 * 1024));
#ifdef USE_PAGING
init_paging(user_paddr, free_paddr);
#endif /* USE_PAGING */
#endif /* USE_FREEMEM */
/* initialize user stack */
init_user_stack_and_env();
/* set trap vector */
csr_write(stvec, &encl_trap_handler);
/* prepare edge & system calls */
init_edge_internals();
/* set timer */
init_timer();
/* Enable the FPU */
csr_write(sstatus, csr_read(sstatus) | 0x6000);
debug("eyrie boot finished. drop to the user land ...");
/* booting all finished, droping to the user land */
return;
}