#include "clib.h" #include "phmem.h" #define MEMORY 32768 /* * qui c'e` il gestore delle pagine di memoria. * ad ogni pagina e` associato un contatore che indica da quanti task * e` utilizzata. quando il contatore e` 0 la pagina e` libera. * la massima quantita` di memoria e` determinata dalla costante * MAX_PAGES. nota che indica il numero massimo di pagine allocabili * a partire da FIRST_PAGE, che e` la prima pagina utilizzabile, mentre * LAST_PAGE e` l'ultima pagina utilizzabile. * * esempio di come viene caricato il tutto : * * * * ____________ indirizzo limite per l'heap, massimo IBMH + #MEMORY * | HEAP | * | | * |________|__ Indirizzo Base della Memoria Heap (IBMH) * | kernel | * |________|___ indirizzo base del kernel * * ..... ______________ eventuali programmi che usano memoria > 1Mb, * | ????? | come ad esempio smartdrv * |___________ 110000h * | HMA | * |________|__ 100000h * | | * |bios/video/UMB * |________|__ 0A0000h * | dos | * |________|__ 000000h * * * * NOTA: la prima pagina di memoria non puo` avere indirizzo < di 110000h * * NOTA: queste funzioni non devono essere interrotte dallo scheduler * * * LREV 23/sept/97 */ #define MAX_PAGES (MEMORY/4) #define LAST_PAGE last_page #define FIRST_PAGE first_page #define MEM_START (FIRST_PAGE * 4096) // array, tiene taccia delle pagine libere/occupate // allineato a cache-line static s8 mem_pages[MAX_PAGES];// _align(32); // numero di pagine UTILIZZABILI (che e` sempre <= MAX_PAGES) static int num_pages; // PRIMA pagina utilizzabile static int last_page; // indirizzo ULTIMA pagina UTILIZZABILE static int first_page; phaddr_t alloc_free_pages(int num) { int count = num, i; for (i = 0; i < num_pages; i++) { if (mem_pages[i] == 0) { // se e` una pagina libera if (--count == 0) { int j; for (j = 0; j < num; j++) { mem_pages[i-j] = 1; // marca come usate } i = (i - num + 1) * 4096+MEM_START; ASSERT((i shr 12) >= FIRST_PAGE); ASSERT((i shr 12) <= LAST_PAGE); return (phaddr_t)i; } } else count = num; } WARNING("return NULL"); return 0; } phaddr_t alloc_free_page(void) { int i; for (i = 0; i < num_pages; i++) if (mem_pages[i] == 0) { mem_pages[i] = 1; i = i*4096+MEM_START; return (phaddr_t)i; } WARNING("return NULL"); return 0; } phaddr_t alloc_pages_at(phaddr_t base, int num) { int page = (u32)base >> 12, i; for (i = 0; i < num; i++, page++) { if (page >= FIRST_PAGE && page <= LAST_PAGE) { mem_pages[page - FIRST_PAGE]++; ASSERT(mem_pages[page - FIRST_PAGE] > 0); } else { WARNING("return NULL"); return 0; } } return base; } int free_pages(phaddr_t a, int num) { int page = (u32)a >> 12, i; for (i = 0; i < num; i++, page++) { if ((page >= FIRST_PAGE) && (page <= LAST_PAGE)) { if (mem_pages[page - FIRST_PAGE] > 0) mem_pages[page - FIRST_PAGE]--; return 0; } else { WARNING("EFAUL in page %xh", page); return EFAULT; } } return 0; /* se num == 0 */ } int free_page(phaddr_t a) { int page = (u32)a >> 12; if (page >= FIRST_PAGE && page <= LAST_PAGE) { if (mem_pages[page - FIRST_PAGE] > 0) --(mem_pages[page - FIRST_PAGE]); return 0; } WARNING("EFAUL in page %xh", page); return EFAULT; } int ph_memory_setup(phaddr_t heap_base, int npages) { FIRST_PAGE = (u32)(heap_base + 0xFFF) >> 12; // arrotonda per eccesso num_pages = npages; if (num_pages > MAX_PAGES) num_pages = MAX_PAGES; LAST_PAGE = (FIRST_PAGE + num_pages) - 1; ASSERT(FIRST_PAGE >= 272); DEBUG_VERBOSE("first page %xh ", FIRST_PAGE); DEBUG_VERBOSE("last page %xh ", LAST_PAGE); DEBUG_VERBOSE("num_pages %xh\n", num_pages); return num_pages; } int get_free_pages(void) { int f = 0, i; for (i = 0; i < num_pages; i++) if (mem_pages[i] == 0) f++; return f; } int get_total_pages(void) { return num_pages; } phaddr_t get_fault_address(void) { return (phaddr_t)(LAST_PAGE shl 12) + 4096; }