static void signal(void *unused, uintptr_t arg, struct pbuf *pbuf) { debug("Signal function called\n"); L4_Msg_t msg; L4_MsgClear(&msg); L4_MsgLoad(&msg); L4_MsgTag_t tag = L4_Send((L4_ThreadId_t) arg); if (L4_IpcFailed(tag)) { L4_Word_t ec = L4_ErrorCode(); printf("%s: IPC error\n", __FUNCTION__); sos_print_error(ec); assert(!(ec & 1)); } call_pbuf = pbuf; }
/* * Init function to initialise the page table entries */ L4_Word_t pager_init(L4_Word_t low, L4_Word_t high) { //The frames have been used to set up page table entries as well page_table = (sos_PTE*) low; // Use a simple algaebric formula to calculate optimum size of page table for the // amount of memory available //new_low points to the memory to be used now, memory low -> new_low is the pagetable new_low = ((double)high*sizeof(sos_PTE)+PAGESIZE*(double)low)/ (double)(PAGESIZE+sizeof(sos_PTE)); // align it new_low = (new_low/PAGESIZE)*PAGESIZE + PAGESIZE; numPTE = (high-new_low)/PAGESIZE; printf("low: %lx new_low: %lx high: %lx numPTE: %d \n", low, new_low, high, numPTE); //printf("value of swap memory %p \n",swap_table); // initialize the empty page table. for (int i = 0; i < numPTE; i++) { page_table[i].tid = L4_nilthread; page_table[i].referenced = 0; page_table[i].dirty = 0; page_table[i].being_updated = 0; page_table[i].error_in_transfer = 0; page_table[i].pinned = 0; } for(int i=0;i<MAX_SWAP_ENTRIES;i++) { swap_table[i].tid = L4_nilthread; swap_table[i].offset = PTE_SENTINEL; //Initially all entries are free so each points to the next one in the table swap_table[i].next_free = i+1; } // add a guard page against stack overflows and let it map to 0 L4_Word_t guardPage = 0x7000000; L4_PhysDesc_t phys = L4_PhysDesc(0, L4_DefaultMemory); L4_Fpage_t targetFpage = L4_FpageLog2(guardPage, 12); L4_Set_Rights(&targetFpage, L4_Readable); if ( !L4_MapFpage(L4_Myself(), targetFpage, phys) ) { sos_print_error(L4_ErrorCode()); printf(" Can't map guard page\n"); } return new_low; }
/* * Function invoked by roottask on pagefault */ int pager(L4_ThreadId_t tid, L4_Msg_t *msgP) { send = 1; // Get the faulting address L4_Word_t addr = L4_MsgWord(msgP, 0); L4_Word_t physicalAddress = 0; L4_Word_t permission = 0; L4_MsgTag_t tag; // Alignment addr = (addr / PAGESIZE)*PAGESIZE; tag = L4_MsgMsgTag(msgP); L4_Word_t access_type = L4_Label(tag) & 0x07; //printf("pager invoked addr=%lx by %lx %lx for access 0x%lx\n", addr,L4_ThreadNo(tid),tid.raw,access_type); // Construct fpage IPC message L4_Fpage_t targetFpage = L4_FpageLog2(addr, 12); if(VIRTUAL(addr)) { if(addr >= BASE_CODE_SEGMENT_ADDRESS) { //Code segment int inPage = isInPage(tid,targetFpage); if(inPage == -1) { //It should be in page table so this should not happen printf("Panic !!! Cannot load the code segment"); } else { physicalAddress = new_low + inPage*PAGESIZE; permission = L4_FullyAccessible; } } else { //Heap and stack int inPage = isInPage(tid, targetFpage); if (inPage == -1) { //We need to check if the page is in swap inPage = isInSwap(tid,targetFpage); mapAddress(tid, targetFpage,inPage); //We dont need to map any addresses here as mapAddresses maps the addresses return send; } else { physicalAddress = new_low+inPage*PAGESIZE; targetFpage = page_table[inPage].pageNo; page_table[inPage].referenced = 1; if(access_type & L4_Writable) { //We now need to set the dirty bit and provide read write access page_table[inPage].dirty = 1; permission = L4_ReadWriteOnly; } else { permission = L4_Readable; } } } } else { // we need to map physical addresses 1:1 physicalAddress = addr; if(addr < new_low) { // This is beyond the low memory range ie the page table // and some other addresses which is below the low range permission = L4_FullyAccessible; } else { // This would be the code segment between the new_low and high permission = L4_Readable; } } L4_Set_Rights(&targetFpage,permission); L4_PhysDesc_t phys = L4_PhysDesc(physicalAddress, L4_DefaultMemory); if ( !L4_MapFpage(tid, targetFpage, phys) ) { sos_print_error(L4_ErrorCode()); printf(" Can't map page at %lx\n", addr); } return send; }