*/
#include <stdio.h>
#include <string.h>
+#include "config.h"
#include "panic.h"
#include "mem.h"
#include "intr.h"
uint32_t size;
};
+void move_stack(uint32_t newaddr); /* defined in startup.s */
+
static void mark_page(int pg, int used);
static void add_memory(uint32_t start, size_t size);
/* A bitmap is used to track which physical memory pages are used, and which
- * are available for allocation by alloc_phys_page.
+ * are available for allocation by alloc_ppage.
*
* last_alloc_idx keeps track of the last 32bit element in the bitmap array
* where a free page was found. It's guaranteed that all the elements before
void init_mem(void)
{
- int i, pg, max_pg = 0;
+ int i, pg, max_used_pg, end_pg = 0;
uint32_t used_end, start, end, sz, total = 0, rem;
const char *suffix[] = {"bytes", "KB", "MB", "GB"};
total += sz;
pg = ADDR_TO_PAGE(end);
- if(max_pg < pg) {
- max_pg = pg;
+ if(end_pg < pg) {
+ end_pg = pg;
}
}
}
printf("Total usable RAM: %u.%u %s\n", total, 100 * rem / 1024, suffix[i]);
- bmsize = max_pg / 8; /* size of the useful bitmap in bytes */
+ /* size of the useful part of the bitmap in bytes padded to 4-byte
+ * boundaries to allow 32bit at a time operations.
+ */
+ bmsize = (end_pg / 32) * 4;
- /* mark all pages occupied by the bitmap as usef */
+ /* mark all pages occupied by the bitmap as used */
used_end = (uint32_t)bitmap + bmsize - 1;
- printf("marking pages up to %x (page: %d) as used\n", used_end, ADDR_TO_PAGE(used_end));
-
- for(i=0; i<=used_end; i++) {
+ max_used_pg = ADDR_TO_PAGE(used_end);
+ printf("marking pages up to %x (page: %d) as used\n", used_end, max_used_pg);
+ for(i=0; i<=max_used_pg; i++) {
mark_page(i, USED);
}
-}
-/* alloc_phys_page finds the first available page of physical memory,
- * marks it as used in the bitmap, and returns its number. If there's
- * no unused physical page, -1 is returned.
- */
-int alloc_ppage(void)
-{
- int i, idx, max, intr_state;
-
- intr_state = get_intr_flag();
- disable_intr();
-
- idx = last_alloc_idx;
- max = bmsize / 4;
-
- while(idx <= max) {
- /* if at least one bit is 0 then we have at least
- * one free page. find it and allocate it.
- */
- if(bitmap[idx] != 0xffffffff) {
- for(i=0; i<32; i++) {
- int pg = idx * 32 + i;
-
- if(IS_FREE(pg)) {
- mark_page(pg, USED);
-
- last_alloc_idx = idx;
-
- /*printf("alloc_phys_page() -> %x (page: %d)\n", PAGE_TO_ADDR(pg), pg);*/
-
- set_intr_flag(intr_state);
- return pg;
- }
- }
- panic("can't happen: alloc_ppage (mem.c)\n");
- }
- idx++;
+#ifdef MOVE_STACK_RAMTOP
+ /* allocate space for the stack at the top of RAM and move it there */
+ if((pg = alloc_ppages(STACK_PAGES, MEM_STACK)) != -1) {
+ printf("moving stack-top to: %x (%d pages)\n", PAGE_TO_ADDR(end_pg) - 4, STACK_PAGES);
+ move_stack(PAGE_TO_ADDR(pg + STACK_PAGES) - 4);
}
+#endif
+}
- set_intr_flag(intr_state);
- return -1;
+int alloc_ppage(int area)
+{
+ return alloc_ppages(1, area);
}
/* free_ppage marks the physical page, free in the allocation bitmap.
*
* CAUTION: no checks are done that this page should actually be freed or not.
- * If you call free_phys_page with the address of some part of memory that was
+ * If you call free_ppage with the address of some part of memory that was
* originally reserved due to it being in a memory hole or part of the kernel
- * image or whatever, it will be subsequently allocatable by alloc_phys_page.
+ * image or whatever, it will be subsequently allocatable by alloc_ppage.
*/
void free_ppage(int pg)
{
}
+int alloc_ppages(int count, int area)
+{
+ int i, dir, pg, idx, max, intr_state, found_free = 0;
+
+ intr_state = get_intr_flag();
+ disable_intr();
+
+ if(area == MEM_STACK) {
+ idx = (bmsize - 1) / 4;
+ max = -1;
+ dir = -1;
+ } else {
+ idx = last_alloc_idx;
+ max = bmsize / 4;
+ dir = 1;
+ }
+
+ while(idx != max) {
+ /* if at least one bit is 0 then we have at least
+ * one free page. find it and try to allocate a range starting from there
+ */
+ if(bitmap[idx] != 0xffffffff) {
+ pg = idx * 32;
+ if(dir < 0) pg += 31;
+
+ for(i=0; i<32; i++) {
+ if(IS_FREE(pg)) {
+ if(!found_free && dir > 0) {
+ last_alloc_idx = idx;
+ found_free = 1;
+ }
+
+ if(alloc_ppage_range(pg, count) != -1) {
+ set_intr_flag(intr_state);
+ return pg;
+ }
+ }
+ pg += dir;
+ }
+ }
+ idx += dir;
+ }
+
+ set_intr_flag(intr_state);
+ return -1;
+}
+
+void free_ppages(int pg0, int count)
+{
+ int i;
+
+ for(i=0; i<count; i++) {
+ free_ppage(pg0++);
+ }
+}
+
int alloc_ppage_range(int start, int size)
{
int i, pg = start;
+ int intr_state;
+
+ intr_state = get_intr_flag();
+ disable_intr();
/* first validate that no page in the requested range is allocated */
for(i=0; i<size; i++) {
for(i=0; i<size; i++) {
mark_page(pg++, USED);
}
+
+ set_intr_flag(intr_state);
return 0;
}
}
}
+void print_page_bitmap(void)
+{
+ int i;
+
+ for(i=0; i<bmsize/4; i++) {
+ if((i & 3) == 0) {
+ uint32_t pg = i * 32;
+ uint32_t addr = PAGE_TO_ADDR(pg);
+ printf("\n%5d [%08x]:", (int)pg, (unsigned long)addr);
+ }
+ printf(" %08x", bitmap[i]);
+ }
+ printf("\n");
+}