Beispiel #1
0
void *pager_extend(pid_t pid) {
	int block = get_block();

	if (block < 0)
		return NULL;

	struct pagetable* page_table = get_page_table(pid);
	int page = get_new_page(page_table, block);

	return (void*) (UVM_BASEADDR + (intptr_t) (page << 12));
}
Beispiel #2
0
void pager_fault(pid_t pid, void *addr) {
	struct pagetable* page_table = get_page_table(pid);
	int page_no = get_page_no(addr);
	if (page_has_frame(page_table, page_no)) {
		int frame = page_table->page_frames[page_no];
		mmu_chprot(pid, addr, PROT_READ | PROT_WRITE);
		set_frame_referenced(frame);
	} else {
		int new_frame = get_frame(pid, page_no);
		if (page_has_block(page_table, page_no)) {
			int block = page_table->blocks[page_no];
			mmu_disk_read(block, new_frame);
		}
		page_table->page_frames[page_no] = new_frame;
		mmu_zero_fill(new_frame);
		mmu_resident(pid, addr, new_frame, PROT_READ | PROT_WRITE);
	}
}
Beispiel #3
0
int pager_syslog(pid_t pid, void *addr, size_t len) {
	char *message = (char*) malloc(len + 1);

	struct pagetable* page_table = get_page_table(pid);
	int i = 0, m = 0;
	for (i = 0; i < len; i++) {
		// if pid doest not have permission to access addr+i
		// return -1
		if (!has_permission(page_table, (intptr_t) addr + i))
			return -1;
		int page_no =
				get_page_no(
						(void*) (((intptr_t) addr + i)
								& (~(page_table->page_size - 1))));
		int frame = page_table->page_frames[page_no];
		message[m++] = pmem[frame * page_table->page_size + i];
	}
	printf("pager_syslog pid %d %s\n", (int) pid, message);
	return 0;
}
Beispiel #4
0
// Map a linear range of pages [virt_start, virt_end), pointing at
// phys_start. All parameters must be page aligned.
void map_pages(virtaddr virt_start, virtaddr virt_end, physaddr phys_start)
{
  int bytes = virt_end - virt_start;
  int section_index = virt_start >> 20;
  int page_index = (virt_start << 12) >> 24;
  uint32_t pte = phys_start;

  for(;;)
  {
    uint32_t *pgt = (uint32_t *)get_page_table(section_index, 0);
    do
    {
      pgt[page_index++] = pte;
      pte += PAGE_SIZE;
      bytes -= PAGE_SIZE;
      if (bytes == 0)
        return;
    }
    while (page_index < 0x100);
    page_index = 0;
    section_index++;
  }
}
Beispiel #5
0
// Called by _start. Physical addressing is in effect, but this code is
// linked assuming virtual addresses: only PC-relative references actually
// work. A small stack is available.
void boot_start()
{
  // Clear some bootdata values
  bootdata->initrd_size = 0;

  // Work out phys->virt offset
  bootdata->phys_to_virt = (uint32_t)&_start - bootdata->rom_base;

  // Print all the info we received from the assembly entry point
  DBGSTR("Pycorn bootstrap entered\n");
  DBGINT("rom base: ", bootdata->rom_base);
  DBGINT("machine type: ", bootdata->machtype);
  DBGINT("taglist ptr: ", bootdata->taglist_ptr);
  DBGINT("phys->virt: ", bootdata->phys_to_virt);

  // Work out section sizes
  uint32_t text_size = &__text_end__ - &__text_start__;
  uint32_t data_size = &__data_end__ - &__data_start__;
  uint32_t bss_size = &__bss_end__ - &__bss_start__;
  uint32_t heap_size = &__heap_end__ - &__heap_start__;
  uint32_t stack_size = &__stack_end__ - &__stack_start__;
  uint32_t img_size = text_size + data_size;

  // Parse atags
  int r = parse_atags();
  DBGINT("parse_atags returned ", r);
  (void)r;

  // Work out where the first free page after the image is.
  // We will use this as the starting location to allocate pages, so there
  // had better be some megabytes of memory here. This will change later to
  // a less stupid allocator.
  bootdata->next_free_page = bootdata->rom_base + img_size;
  DBGINT("first free page: ", bootdata->next_free_page);

  // Allocate page directory
  DBGSTR("Allocate page directory\n");
  bootdata->page_directory = alloc_pages_zero(PAGEDIR_SIZE, PAGEDIR_SIZE);
  DBGINT("page directory: ", bootdata->page_directory);
  
  // Set MMU base address
  DBGSTR("Set MMU base address\n");
  mmu_set_base(bootdata->page_directory);

  // Allocate and map page table mappings
  // Page tables are placed linearly at a fixed location to make
  // it possible to find them again later without having to remember
  // where they are.
  // This is kinda scary as we are bootstrapping :)
  DBGSTR("Allocate and map page table mappings\n");
  int ptbl_section = (virtaddr)(&__page_tbl_start__) >> SECTION_SHIFT;
  physaddr ptbl_map = get_page_table(ptbl_section, 1);
  virtaddr ptbl_address = (virtaddr)(&__page_tbl_start__)
      + (ptbl_section * PAGETABLE_SIZE);
  map_pages(ptbl_address, ptbl_address + (PAGE_SIZE * PTBLS_PER_PAGE),
      ptbl_map | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Map page directory
  DBGSTR("Map page directory\n");
  map_pages((virtaddr)&__page_dir_virt__,
      (virtaddr)(&__page_dir_virt__ + PAGEDIR_SIZE),
      bootdata->page_directory | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Map text section of image
  DBGSTR("Map text section\n");
  map_pages((virtaddr)&__text_start__, (virtaddr)&__text_end__,
      bootdata->rom_base | PTB_ROM | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Map data section of image
  DBGSTR("Map data section\n");
  physaddr data_phys = bootdata->rom_base + text_size;
  map_pages((virtaddr)&__data_start__, (virtaddr)&__data_end__,
      data_phys | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Allocate and map bss section
  DBGSTR("Allocate and map bss\n");
  physaddr bss_phys = alloc_pages_zero(bss_size, PAGE_SIZE);
  map_pages((virtaddr)&__bss_start__, (virtaddr)&__bss_end__,
      bss_phys | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Allocate and map heap section
  DBGSTR("Allocate and map heap\n");
  physaddr heap_phys = alloc_pages_zero(heap_size, PAGE_SIZE);
  map_pages((virtaddr)&__heap_start__, (virtaddr)&__heap_end__,
      heap_phys | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Allocate and map stack section
  DBGSTR("Allocate and map stack\n");
  physaddr stack_phys = alloc_pages_zero(stack_size, PAGE_SIZE);
  map_pages((virtaddr)&__stack_start__, (virtaddr)&__stack_end__,
      stack_phys | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Map debug UART - we assume no more than a page is needed
  DBGSTR("Mapping debug UART\n");
  map_pages((virtaddr)&__dbg_serial_virt__, 
      (virtaddr)(&__dbg_serial_virt__ + PAGE_SIZE),
      (physaddr)&__dbg_serial_phys__ | PTB_RW | PTB_EXT);

  // Map boot data page
  DBGSTR("Mapping boot data\n");
  map_pages((virtaddr)&__bootdata_virt__,
      (virtaddr)(&__bootdata_virt__ + PAGE_SIZE),
      (physaddr)bootdata | PTB_RW | PTB_CACHE | PTB_BUFF | PTB_EXT);

  // Map the initrd if there was one
  if (bootdata->initrd_size)
  {
    // The initrd address may not be a page multiple as u-boot has
    // its own header on the file, so we need to align it.
    physaddr map_start = PAGEALIGN_DOWN(bootdata->initrd_phys);
    uint32_t map_len = PAGEALIGN_UP(bootdata->initrd_phys +
        bootdata->initrd_size) - map_start;
    // We also need to calculate the offset and offset the virtual
    // address by the matching amount.
    uint32_t offset = bootdata->initrd_phys - map_start;
    bootdata->initrd_virt = (virtaddr)&__initrd_map_start__ + offset;

    DBGSTR("Map initrd\n");
    map_pages((virtaddr)&__initrd_map_start__,
        (virtaddr)(&__initrd_map_start__ + map_len),
        map_start | PTB_ROM | PTB_CACHE | PTB_BUFF | PTB_EXT);
  }

  // Self-map MMU enabling code
  // The page which contains the MMU enable function must be mapped
  // with phys==virt address, otherwise bad stuff happens. We do this
  // by stuffing in a 1MB section mapping for this address, which may
  // overwrite an actual page table mapping (it's saved and restored
  // later on).
  DBGSTR("Self-map MMU enabling code\n");
  mmu_enable_func mmu_enable_phys = &mmu_enable - bootdata->phys_to_virt;
  physaddr selfmap_addr = (physaddr)mmu_enable_phys;
  int selfmap_index = selfmap_addr >> SECTION_SHIFT;
  selfmap_addr = selfmap_index << SECTION_SHIFT;
  uint32_t *pgd = (uint32_t *)bootdata->page_directory;
  uint32_t old_pde = pgd[selfmap_index];
  pgd[selfmap_index] = selfmap_addr | PGD_ROM | PGD_SECTION;

  // Enable MMU. This doesn't return, it goes to boot_after_mmu.
  DBGSTR("Enable MMU\n");
  mmu_enable_phys(selfmap_index, old_pde, &boot_after_mmu);
}