PLEASE tell me why you don't just use the 20-line "vmalloc()" function I
already wrote for you?
It works for all cases - and since you do need to load the kernel into
memory anyway, it's not using any more memory than your existing code. And
it's infinitely more flexible to have a clearly separated load-process,
than having to have some load happen at reboot time (whether by init or by
anything else).
And since the kernel is fully working at the load time, you can even do
things like swap out pages in order to make room for the kernel at the
right place. So you can even do something like this:
int alloc_kernel_pages(unsigned long *array, int nr_pages,
unsigned long min_address)
{
void *bad_page_list = NULL;
int i = 0, retval;
while (i < nr_pages) {
unsigned long page = __get_free_page(GFP_USER);
if (!page)
goto oom;
if (page < min_address) {
*(void **)page = bad_page_list;
bad_page_list = (void *)page;
continue;
}
array[i] = page;
i++;
}
retval = 0;
out:
while (bad_page_list) {
unsigned long page = (unsigned long) bad_page_list;
bad_page_list = *(void **)bad_page_list;
free_page(page);
}
return retval;
oom:
while (i > 0)
free_page(array[--i]);
retval = -ENOMEM;
goto out;
}
and now you are guaranteed that all the allocated pages are above a
certain mark (change the "min_address" to be a "validity callback" or
whatever if you want to be fancy and allow arbitrary rules, which is good
if you want to allow pages in the low 1M on x86, for example), which means
that your final reboot stage is _much_much_ simpler and you don't ever
have to worry about overlap.
Use one of the pages to allocate the memcpy() trampoline and the actual
data structures used for the copy, for example. Use the rest for the
actual kernel data.
Keep it simple.
Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/