29 |
/* The program name. */ |
/* The program name. */ |
30 |
char *program_name = "wortel"; |
char *program_name = "wortel"; |
31 |
|
|
32 |
rootserver_t physmem; |
const char *mod_names[] = { "physmem-mod", "task-mod", "root-fs-mod" }; |
33 |
|
|
34 |
|
/* For the boot components, find_components() must fill in the start |
35 |
|
and end address of the ELF images in memory. The end address is |
36 |
|
one more than the last byte in the image. */ |
37 |
|
struct wortel_module mods[MOD_NUMBER]; |
38 |
|
|
39 |
|
unsigned int mods_count; |
40 |
|
|
41 |
|
|
42 |
/* Return the number of memory descriptors. */ |
/* Return the number of memory descriptors. */ |
59 |
static void |
static void |
60 |
load_components (void) |
load_components (void) |
61 |
{ |
{ |
62 |
if (!physmem.low) |
unsigned int i; |
63 |
|
|
64 |
|
for (i = 0; i < mods_count; i++) |
65 |
|
loader_add_region (mods[i].name, mods[i].start, mods[i].end); |
66 |
|
|
67 |
|
if (!mods[MOD_PHYSMEM].start) |
68 |
panic ("No physical memory server found"); |
panic ("No physical memory server found"); |
|
loader_add_region ("physmem-mod", physmem.low, physmem.high); |
|
69 |
|
|
70 |
loader_elf_load ("physmem-server", physmem.low, physmem.high, |
loader_elf_load ("physmem-server", mods[MOD_PHYSMEM].start, |
71 |
&physmem.low, &physmem.high, &physmem.ip); |
mods[MOD_PHYSMEM].end, |
72 |
|
&mods[MOD_PHYSMEM].start, &mods[MOD_PHYSMEM].end, |
73 |
|
&mods[MOD_PHYSMEM].ip); |
74 |
loader_remove_region ("physmem-mod"); |
loader_remove_region ("physmem-mod"); |
75 |
} |
} |
76 |
|
|
77 |
|
|
78 |
|
/* The maximum number of fpages required to cover a page aligned range |
79 |
|
of memory. This is k if the maximum memory range size to cover is |
80 |
|
2^(k + min_page_size_log2), which can be easily proved by |
81 |
|
induction. The minimum page size in L4 is at least 2^10. */ |
82 |
|
#define MAX_FPAGES (sizeof (l4_word_t) * 8 - 10) |
83 |
|
|
84 |
|
|
85 |
|
/* Determine the fpages required to cover the bytes from START to END, |
86 |
|
which must be aligned to the minimal page size supported by the |
87 |
|
system. Returns the number of fpages required to cover the range, |
88 |
|
and returns that many fpages (with maximum accessibility) in |
89 |
|
FPAGES. At most MAX_FPAGES fpages will be returned. */ |
90 |
|
unsigned int |
91 |
|
make_fpages (l4_word_t start, l4_word_t size, l4_fpage_t *fpages) |
92 |
|
{ |
93 |
|
l4_word_t min_page_size = getpagesize (); |
94 |
|
l4_word_t end = (start + size + min_page_size - 1) & ~(min_page_size - 1); |
95 |
|
unsigned int nr_fpages = 0; |
96 |
|
|
97 |
|
if (!size) |
98 |
|
return 0; |
99 |
|
|
100 |
|
if (start & ~(min_page_size - 1)) |
101 |
|
panic ("make_fpages: START is not aligned to minimum page size"); |
102 |
|
if (end & ~(min_page_size - 1)) |
103 |
|
panic ("make_fpages: START is not aligned to minimum page size"); |
104 |
|
|
105 |
|
/* END is at least one MIN_PAGE_SIZE larger than START. */ |
106 |
|
nr_fpages = 0; |
107 |
|
while (start < end) |
108 |
|
{ |
109 |
|
fpages[nr_fpages] = l4_fpage (start, end - start); |
110 |
|
start += l4_size (fpages[nr_fpages]); |
111 |
|
nr_fpages++; |
112 |
|
} |
113 |
|
return nr_fpages; |
114 |
|
} |
115 |
|
|
116 |
|
|
117 |
static void |
static void |
118 |
start_components (void) |
start_components (void) |
119 |
{ |
{ |
123 |
l4_msg_t msg; |
l4_msg_t msg; |
124 |
l4_msg_tag_t msg_tag; |
l4_msg_tag_t msg_tag; |
125 |
|
|
126 |
if (physmem.low & (min_page_size - 1)) |
if (mods[MOD_PHYSMEM].start & (min_page_size - 1)) |
127 |
panic ("physmem is not page aligned on this architecture"); |
panic ("physmem is not page aligned on this architecture"); |
128 |
if (physmem.low > physmem.high) |
if (mods[MOD_PHYSMEM].start > mods[MOD_PHYSMEM].end) |
129 |
panic ("physmem has invalid memory range"); |
panic ("physmem has invalid memory range"); |
130 |
if (physmem.ip < physmem.low || physmem.ip > physmem.high) |
if (mods[MOD_PHYSMEM].ip < mods[MOD_PHYSMEM].start |
131 |
|
|| mods[MOD_PHYSMEM].ip > mods[MOD_PHYSMEM].end) |
132 |
panic ("physmem has invalid IP"); |
panic ("physmem has invalid IP"); |
133 |
|
|
134 |
/* Thread nr is next available after rootserver thread nr, |
/* Thread nr is next available after rootserver thread nr, |
135 |
version part is 2 (rootserver is 1). */ |
version part is 2 (rootserver is 1). */ |
136 |
l4_thread_id_t physmem_server |
l4_thread_id_t physmem_server |
137 |
= l4_global_id (l4_thread_no (l4_myself ()) + 2, |
= l4_global_id (l4_thread_no (l4_myself ()) + 2, 2); |
|
2); |
|
138 |
/* The UTCB location below is only a hack. We also need a way to |
/* The UTCB location below is only a hack. We also need a way to |
139 |
specify the maximum number of threads (ie the size of the UTCB |
specify the maximum number of threads (ie the size of the UTCB |
140 |
area), for example via ELF symbols, or via the command line. |
area), for example via ELF symbols, or via the command line. |
161 |
|
|
162 |
l4_msg_clear (&msg); |
l4_msg_clear (&msg); |
163 |
l4_set_msg_label (&msg, 0); |
l4_set_msg_label (&msg, 0); |
164 |
l4_msg_append_word (&msg, physmem.ip); |
l4_msg_append_word (&msg, mods[MOD_PHYSMEM].ip); |
165 |
l4_msg_append_word (&msg, 0); |
l4_msg_append_word (&msg, 0); |
166 |
l4_msg_load (&msg); |
l4_msg_load (&msg); |
167 |
msg_tag = l4_send (physmem_server); |
msg_tag = l4_send (physmem_server); |
170 |
l4_error_code ()); |
l4_error_code ()); |
171 |
|
|
172 |
{ |
{ |
173 |
l4_fpage_t *fpages; |
l4_fpage_t fpages[MAX_FPAGES]; |
174 |
unsigned int nr_fpages = 0; |
unsigned int nr_fpages; |
175 |
l4_word_t start = physmem.low; |
l4_word_t start = mods[MOD_PHYSMEM].start; |
176 |
l4_word_t end = (physmem.high + min_page_size) & ~(min_page_size - 1); |
l4_word_t size = (mods[MOD_PHYSMEM].end - start + min_page_size) |
177 |
l4_word_t region; |
& ~(min_page_size - 1); |
178 |
|
|
179 |
/* We want to grant all the memory for the physmem binary image |
/* We want to grant all the memory for the physmem binary image |
180 |
with the first page fault, but we might have to send several |
with the first page fault, but we might have to send several |
181 |
fpages. So we first create a list of all fpages we need, then |
fpages. So we first create a list of all fpages we need, then |
182 |
we serve one after another, providing the one containing the |
we serve one after another, providing the one containing the |
183 |
fault address last. */ |
fault address last. */ |
184 |
|
nr_fpages = make_fpages (start, size, fpages); |
|
/* A page-aligned region of size up to 2^k * min_page_size can be |
|
|
covered by k fpages at most (proof by induction). At this |
|
|
point, END is at least one MIN_PAGE_SIZE larger than START. */ |
|
|
region = (end - start) / min_page_size; |
|
|
while (region > 0) |
|
|
{ |
|
|
nr_fpages++; |
|
|
region >>= 1; |
|
|
} |
|
|
fpages = alloca (sizeof (l4_fpage_t) * nr_fpages); |
|
|
|
|
|
nr_fpages = 0; |
|
|
while (start < end) |
|
|
{ |
|
|
fpages[nr_fpages] = l4_fpage (start, end - start); |
|
|
start += l4_size (fpages[nr_fpages]); |
|
|
nr_fpages++; |
|
|
} |
|
185 |
|
|
186 |
/* Now serve page requests. */ |
/* Now serve page requests. */ |
187 |
while (nr_fpages) |
while (nr_fpages) |
201 |
if (l4_untyped_words (msg_tag) != 2 || l4_typed_words (msg_tag) != 0) |
if (l4_untyped_words (msg_tag) != 2 || l4_typed_words (msg_tag) != 0) |
202 |
panic ("Invalid format of page fault message"); |
panic ("Invalid format of page fault message"); |
203 |
addr = l4_msg_word (&msg, 0); |
addr = l4_msg_word (&msg, 0); |
204 |
if (addr != physmem.ip) |
if (addr != mods[MOD_PHYSMEM].ip) |
205 |
panic ("Page fault at unexpected address 0x%x (expected 0x%x)", |
panic ("Page fault at unexpected address 0x%x (expected 0x%x)", |
206 |
addr, physmem.ip); |
addr, mods[MOD_PHYSMEM].ip); |
207 |
|
|
208 |
if (nr_fpages == 1) |
if (nr_fpages == 1) |
209 |
i = 0; |
i = 0; |