예제 #1
0
파일: pager.c 프로젝트: gapry/aos-1
/*
 * This function loads the entire elf file into the phsical frames and
 * maps fpages corresponding to virtual address in elf file to the process
 */
int load_code_segment_virtual(char *elfFile,L4_ThreadId_t new_tid) {
  uint32_t min[2];
  uint32_t max[2];
  elf_getMemoryBounds(elfFile, 0, (uint64_t*)min, (uint64_t*)max);
  //Now we need to reserve memory between min and max
  L4_Word_t lower_address = ((L4_Word_t) min[1] / PAGESIZE) * PAGESIZE; 
  L4_Word_t upper_address = ((L4_Word_t) max[1] / PAGESIZE) * PAGESIZE;
 
  while(lower_address <= upper_address) {
    L4_Word_t frame = frame_alloc();
    if(!frame) {
      //Oops out of frames
      unmap_process(new_tid);
      return -1;
    } else {
      L4_Fpage_t targetpage = L4_FpageLog2(lower_address,12);
      lower_address += PAGESIZE;
      //Now map fpage
      L4_Set_Rights(&targetpage,L4_FullyAccessible);
      L4_PhysDesc_t phys = L4_PhysDesc(frame, L4_DefaultMemory);
      //Map the frame to root task but enter entries in pagetable with tid since we will update the mappings once elf loading is done
      if (L4_MapFpage(L4_Myself(), targetpage, phys) ) {
	page_table[(frame-new_low)/PAGESIZE].tid = new_tid;
	page_table[(frame-new_low)/PAGESIZE].pinned = 1;
	page_table[(frame-new_low)/PAGESIZE].pageNo = targetpage;
      } else {
	unmap_process(new_tid);
      }
    }
  }
  //Now we have mapped the pages, now load elf_file should work with the virtual addresses
  if(elf_loadFile(elfFile,0) == 1) {
      //Elffile was successfully loaded
      //Map the fpages which were previously mapped to Myself to the tid
    for(int i=0;i<numPTE;i++) {
      if(L4_ThreadNo(new_tid) == L4_ThreadNo(page_table[i].tid)) {
	//Now remap the pages which were mapped to root task to the new tid
	L4_UnmapFpage(L4_Myself(),page_table[i].pageNo);
	L4_PhysDesc_t phys = L4_PhysDesc(new_low + i * PAGESIZE, L4_DefaultMemory);
	if(!L4_MapFpage(new_tid, page_table[i].pageNo, phys)) {
	  unmap_process(new_tid);
	  return -1;
	}
      }
    }
  } else {
    unmap_process(new_tid);
  }
  //Remove later
  L4_CacheFlushAll();
  return 0;
}
예제 #2
0
파일: tlb.c 프로젝트: CSU-GH/okl4_3.0
void
l4_map_page(mm_context_t *context, L4_Fpage_t fpage, unsigned long address,
		unsigned long attrib)
{
	unsigned long dest_addr, src_addr;
	L4_Fpage_t vpage;
	L4_PhysDesc_t pdesc;
	int rwx;

	src_addr = L4_Address(fpage);
#if 0
	if (src_addr >= vmalloc_ms_base && src_addr <= vmalloc_ms_base + vmalloc_ms_size) {
		// Within the vmalloc bounds so use the new depriv mapping
		dest_addr = address & 0xfffff000;
		vpage = L4_Fpage(dest_addr, L4_Size(fpage));
		pdesc = L4_PhysDesc(src_addr + vmalloc_ms_virt_to_phys_offset, attrib);
		rwx = L4_Rights(fpage);

		L4_FpageAddRightsTo(&vpage, rwx);
		L4_MapFpage(context->space_id, vpage, pdesc);
	} else {
#endif

		eas_map(context->eas, fpage, address, attrib);
//	}
}
#endif

#if defined(CONFIG_CELL)
unsigned long last_vstart = -1UL;
unsigned long last_vend, last_seg;

int
okl4_find_segment(unsigned long vaddr, unsigned long *offset, unsigned long *seg)
{
	okl4_env_segments_t *segments = OKL4_ENV_GET_SEGMENTS("SEGMENTS");
	unsigned long i;

	assert(segments);
	for (i = 0; i < segments->num_segments; i++) {
	    if (vaddr >= segments->segments[i].virt_addr &&
		    vaddr <= (segments->segments[i].virt_addr + 
			segments->segments[i].size - 1)) {
			*offset = vaddr - segments->segments[i].virt_addr;
			*seg = segments->segments[i].segment;

			/* Cache lookup */
			last_vstart = segments->segments[i].virt_addr;
			last_vend = last_vstart + segments->segments[i].size - 1;
			last_seg = segments->segments[i].segment;
			return 1;
		}
	}

	return 0;
}
예제 #3
0
파일: pager.c 프로젝트: gapry/aos-1
/*
 * This function is the controller function which maps virtual addresses to physical frames. 
 */
static L4_Word_t mapAddress(L4_ThreadId_t tid, L4_Fpage_t fpage, int swapIndex)
{    
    // allocate a new frame
    int evicted_not_dirty = 0;
    L4_Word_t physAddress = frame_alloc();
    int i = 0;
    //int head = 0, oldHead = 0;
    if(physAddress == 0) {
      int evicted = evictPage();
      //If page replacement aborted if all pages in page table are currently being updated, abort
      if(evicted == -1) {
	return -1;
      }

      if(page_table[evicted].dirty == 1) {
	//We need to write it to swap
        writeToSwap(evicted,swapIndex,tid,fpage);
      } else {
	evicted_not_dirty = 1;
      }
      i = evicted;
    } else {
      i = (physAddress - new_low)/PAGESIZE;
    }
    if(physAddress != 0 || evicted_not_dirty) {
      //We have a frame avialable to us or a swapout is not necessary
      if(swapIndex != -1) {
	//We need to read from the swap and overwrite the physical frame with it
	//We need to read from the swap and signal to it that there was no swapout
	readFromSwap(swapIndex,i,0,tid,fpage);
      } else {
	//We do not have to read from swap, we just overwrite the frame
	//Page was not swapped out neither swapped in
	page_table[i].tid = tid;
	page_table[i].pageNo = fpage;
	page_table[i].being_updated = 0;
	page_table[i].referenced = 1;
	page_table[i].dirty = 0;
	send = 1;
	L4_Set_Rights(&fpage,L4_Readable);  
	L4_PhysDesc_t phys = L4_PhysDesc(new_low + i * PAGESIZE, L4_DefaultMemory);
	//update the size of the process table
	update_process_table_size(tid,1);
	L4_MapFpage(tid, fpage,phys);
      }
    }
    return physAddress;
}
예제 #4
0
파일: pager.c 프로젝트: gapry/aos-1
/*
 * 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;
}
예제 #5
0
파일: clock.c 프로젝트: gz/aos10
/**
 * Starts the clock driver. This will map the memory region where the
 * registers are in uncached mode, start the time stamp timer register
 * and enable the interrupts for our time stamp timer and the general
 * purpose timer 0.
 *
 * @return CLOCK_R_OK if the timer is started successfully
 * 		   CLOCK_R_FAIL if the memory region could not be mapped
 */
int start_timer(void) {
	assert(!driver_initialized);

	// initialize variables
	timestamp_irq_tid =  L4_GlobalId(NSLU2_TIMESTAMP_IRQ, 1);
	timer0_irq_tid = L4_GlobalId(NSLU2_TIMER0_IRQ, 1);
	registers_fpage = L4_FpageLog2(NSLU2_OSTS_PHYS_BASE, 12);

	// Set up uncached memory mapping for registers
	L4_Set_Rights(&registers_fpage, L4_FullyAccessible);
	L4_PhysDesc_t phys = L4_PhysDesc(NSLU2_OSTS_PHYS_BASE, L4_UncachedMemory);

	if(L4_MapFpage(L4_Pager(), registers_fpage, phys)) {

		// enable timer0 interrupts
		TIMER0_ONE_SHOT(0);
		TIMER0_STOP();
		(*(L4_Word_t*)OST_STATUS) |= (0x1 << 0);
		int res = L4_AssociateInterrupt(timer0_irq_tid, root_thread_g);
		assert(res);

		// start timestamp timer
		*((L4_Word_t*)OST_TS) = 0x00000000; // reset counter

		// enable timestamp interrupts
		(*(L4_Word_t*)OST_STATUS) |= (0x1 << 2);
		res = L4_AssociateInterrupt(timestamp_irq_tid, root_thread_g);
		assert(res);

		driver_initialized = TRUE;

		return CLOCK_R_OK;
	}
	else {
		return CLOCK_R_FAIL;
	}
}
예제 #6
0
파일: pager.c 프로젝트: gapry/aos-1
/*
 * 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;
}
예제 #7
0
파일: pager.c 프로젝트: gapry/aos-1
/*
 * Callback function to nfs_read from swapfile
 * Always replies to the thread
 */
void pager_read_callback(uintptr_t token,int status, fattr_t *attr, int bytes_read,char *data) {
  struct page_token *token_val = (struct page_token *) token;
  int pagetableIndex = token_val -> pageIndex;
  int byte_index = token_val -> chunk_index;
  int swapIndex = token_val -> swapIndex;

  if(status != 0) {
    page_table[pagetableIndex].error_in_transfer = 1;
  } else {
    //Copy the data read to memory
    char *memstart = (char *) (new_low + pagetableIndex * PAGESIZE + byte_index*NFS_READ_SIZE); 
    memcpy(memstart,data,NFS_READ_SIZE);
  }
    
  page_table[pagetableIndex].read_bytes_transferred += NFS_READ_SIZE;

  //Check if all the callbacks have been received
  if(page_table[pagetableIndex].read_bytes_transferred == PAGESIZE) {
    if(page_table[pagetableIndex].error_in_transfer == 1) {
      //The memory in pagetable is inconsistent so the best thing would be to mark the 
      //page table entry as unreferenced and hopefully its evicted soon
      //If this occurs for a free frame its best to free the frame
      //This condition is not required we would always want to free the frame(think and remove)
      if(!token_val -> writeToSwapIssued) {
        frame_free(new_low + pagetableIndex * PAGESIZE);
      }
      //Unmap the page table page whose memory we corrupted
      L4_UnmapFpage(page_table[pagetableIndex].tid,page_table[pagetableIndex].pageNo);

      page_table[pagetableIndex].tid = L4_nilthread;
      page_table[pagetableIndex].referenced = 0;
      page_table[pagetableIndex].dirty = 0;

    } else {
      //Free up the swap entry from which we read in
      swap_table[swapIndex].tid = L4_nilthread;
      swap_table[swapIndex].next_free = head_free_swap;
      head_free_swap = swapIndex;
      //Update page table
      page_table[pagetableIndex].tid = token_val -> destination_tid;
      page_table[pagetableIndex].pageNo = token_val -> destination_page;
      page_table[pagetableIndex].referenced = 1;
      page_table[pagetableIndex].dirty = 0;
      //Unmap the page which was written out
      if(token_val -> writeToSwapIssued) {
        L4_UnmapFpage(token_val -> source_tid,token_val -> source_page);
      }
      L4_Set_Rights(&(token_val -> destination_page),L4_Readable);  
      L4_PhysDesc_t phys = L4_PhysDesc(new_low + pagetableIndex * PAGESIZE, L4_DefaultMemory);
      L4_MapFpage(token_val -> destination_tid, token_val -> destination_page, phys);
      L4_CacheFlushAll();
      //Everything went fine
    }
    L4_Msg_t msg;
    L4_MsgClear(&msg);
    L4_MsgLoad(&msg);
    L4_Reply(token_val -> destination_tid);
    //Update the process table size
    update_process_table_size(token_val -> destination_tid,1);
    page_table[pagetableIndex].being_updated = page_table[pagetableIndex].error_in_transfer = 0;
  }
  free(token_val);
}
예제 #8
0
파일: pager.c 프로젝트: gapry/aos-1
/*
 * Callback function to nfs_write to swapfile, Issues a read from swap if necessary
 * Replies to the thread if only swapout need to be done and no swapin
 */
void pager_write_callback(uintptr_t token, int status, fattr_t *attr) {
  struct page_token *token_val = (struct page_token *) token;
  int pageIndex = token_val -> pageIndex;
  int swapIndex = token_val -> swapIndex;

  if(status != 0) {
    //Something bad happened so we cannot overwrite the page content, lets delay for 
    //next page fault
    page_table[pageIndex].error_in_transfer = 1;
  }
  
  //Increment the bytes transferred for each callback
  page_table[pageIndex].write_bytes_transferred += NFS_WRITE_SIZE;
  
  //If all callbacks have been received without an error we have a successful write
  if(page_table[pageIndex].write_bytes_transferred == PAGESIZE) {
    if(!page_table[pageIndex].error_in_transfer) {
        //Update the swap table
	swap_table[swapIndex].tid = token_val -> source_tid;
	swap_table[swapIndex].pageNo = token_val -> source_page;
	
	//Check if swapin needs to be done
	if(token_val -> send_reply) {
	  L4_PhysDesc_t phys = L4_PhysDesc(new_low + pageIndex * PAGESIZE, L4_DefaultMemory);
          L4_Set_Rights(&(token_val -> destination_page),L4_Readable);  
	  //Map the page to the new tid
	  L4_MapFpage(token_val -> destination_tid, token_val -> destination_page,phys);
	  //Update page table
	  page_table[pageIndex].tid = token_val -> destination_tid;
	  page_table[pageIndex].pageNo = token_val -> destination_page;
	  page_table[pageIndex].referenced = 1;
	  page_table[pageIndex].dirty = 0;
	} else {
	  //There is a read coming up
          readFromSwap(token_val -> swapIndexToBeReadIn,pageIndex,1,token_val -> destination_tid,token_val -> destination_page);
	}
	
    } else {
      // If there is an error in transfer, currently we have nothing to do
      //Since this write was invalidated we undo the change
      swap_file_size -= PAGESIZE;
      //Undo the swap that was allocated
      swap_table[swapIndex].next_free = head_free_swap;
      head_free_swap = swapIndex;
    }
    //If there was an error in transfer (we dont issue swapin even if needed) or
    //there was no swapin after swapoff we reply to faulting tid
    if(token_val -> send_reply || page_table[pageIndex].error_in_transfer) {
      //We clear the error in transfer value and being updated since the work is done
      page_table[pageIndex].being_updated = page_table[pageIndex].error_in_transfer = 0;
      //Now send the reply message
      //Update the process table size 
      update_process_table_size(token_val -> source_tid,0);
      L4_Msg_t msg;
      L4_MsgClear(&msg);
      L4_MsgLoad(&msg);
      L4_Reply(token_val ->destination_tid);
    }
  }
  //Free up the token
  free(token_val);
}