Exemple #1
0
/*
 * Copy binary's section into a given mem_area.
 * @mma   -- memory area to hold the section
 * @inode -- inode containing the binary
 * @off   -- offset of the section in the file
 * @len   -- length of the section
 * Note1: section has to be created beforehand.
 * Note2: it is assumed that all the file's pages are loaded in
 *        inode's buffers.
 */
void aout_copy_section(struct mem_area *mma, struct inode *inode,
		off_t off, size_t len)
{
	struct page *page;
	struct klist0_node *tmp;
	struct page *destpg;
	void *to = NULL;
	u32 pgnum, pgoff;
	size_t left, tocopy;

	/* where we start */
	pgnum = (off & NOPAGE_MASK) >> PAGE_SHIFT;
	pgoff = off & PAGE_MASK;
	tmp = mma->m_plist.next;
	left = len;

	while (left > 0) {
		page = inode->i_map.i_pages[pgnum];
		if (!((u32)to & PAGE_MASK)) {
			destpg = klist0_entry(tmp, struct page, area_list);
			to = page_to_addr(destpg);
		}

		if (pgoff)
			tocopy = MIN(left, (size_t)PAGE_SIZE - pgoff);
		else
			tocopy = MIN(left,
					(size_t)(PAGE_SIZE - ((u32)to & PAGE_MASK)));

		/*DPRINT("### copy: %x[%x] to %x[%x], %d bytes\n",
				page_to_addr(page) + pgoff, page->virt, to, destpg->virt,
				tocopy);*/
		memory_copy(to, page_to_addr(page) + pgoff,
				tocopy);

		/* switch to next source page */
		if (pgoff + tocopy == PAGE_SIZE)
			pgnum++;
		else
			pgoff = tocopy;

		left -= tocopy;
		to += tocopy;
		
		if (!((u32)to & PAGE_MASK))
			tmp = tmp->next;
		else
			pgoff = 0;
	}
Exemple #2
0
static void phy_pages_init(e820map_t *e820map)
{
        uint32_t phy_mem_length = 0;
        for (uint32_t i = 0; i < e820map->count; ++i){
                if (e820map->map[i].addr_low > ZONE_HIGHMEM_ADDR) {
                      break;
                }
                if (e820map->map[i].addr_low + e820map->map[i].length_low > ZONE_HIGHMEM_ADDR) {
                        phy_mem_length = ZONE_HIGHMEM_ADDR;
                        break;
                }
                phy_mem_length = e820map->map[i].length_low;
        }

        uint32_t pages_mem_length = sizeof(page_t) * (phy_mem_length / PMM_PAGE_SIZE);
        bzero(phy_pages, pages_mem_length);

        // 物理内存页管理起始地址
        pmm_addr_start = ((uint32_t)phy_pages - KERNBASE + pages_mem_length + PMM_PAGE_SIZE) & PMM_PAGE_MASK;

        for (uint32_t i = 0; i < e820map->count; ++i){
                uint32_t start_addr = e820map->map[i].addr_low;
                uint32_t end_addr = e820map->map[i].addr_low + e820map->map[i].length_low;
                if (start_addr < pmm_addr_start) {
                        start_addr = pmm_addr_start;
                }
                if (end_addr > ZONE_HIGHMEM_ADDR) {
                        end_addr = ZONE_HIGHMEM_ADDR;
                }
                for (uint32_t addr = start_addr; addr < end_addr; addr += PMM_PAGE_SIZE) {
                        phy_pages_count++;
                }
                pmm_addr_end = end_addr;
        }

        assert(pmm_addr_start == page_to_addr(&phy_pages[0]),
                        "phy_pages_init error pmm_start != &page[0]");
        assert(pmm_addr_end - PMM_PAGE_SIZE == page_to_addr(&phy_pages[phy_pages_count-1]),
                        "phy_pages_init error pmm_end != &page[n-1]");
        assert(&phy_pages[0] == addr_to_page(page_to_addr(&phy_pages[0])),
                        "phy_pages_init error addr_to_page error");
        assert(&phy_pages[1] == addr_to_page(page_to_addr(&phy_pages[1])),
                        "phy_pages_init error addr_to_page error");
}
Exemple #3
0
/* Sets the specified page's permission value.  This involves two steps:
 * First, mprotect() is used to set the actual permissions on the page's
 * virtual address range.  After this is completed successfully, the page's
 * Page Table Entry is updated with the new permission value.  (The other bits
 * in the PTE are left unmodified.)
 */
void set_page_permission(page_t page, int perm) {
    assert(page < NUM_PAGES);
    assert(perm == PAGEPERM_NONE || perm == PAGEPERM_READ ||
           perm == PAGEPERM_RDWR);

    /* Call mprotect() to set the memory region's protections. */
    if (mprotect(page_to_addr(page), PAGE_SIZE, pageperm_to_mmap(perm)) == -1) {
        perror("mprotect");
        abort();
    }

    /* Replace old permission with new permission. */
    page_table[page] = (page_table[page] & ~PAGEPERM_MASK) | perm;
}
Exemple #4
0
/* This function unmaps the specified page from the virtual address space,
 * making sure to write the contents of dirty pages back into the swap file.
 */
void unmap_page(page_t page) {
    int ret;

    assert(page < NUM_PAGES);
    assert(num_resident > 0);
    assert(is_page_resident(page));


    /*
     * Step 1:
     * If the page is dirty, seek to the start of the corresponding slot in the
     * swap file and save the page’s contents to the slot.
     */

    /* Only if dirty. */
    if (is_page_dirty(page)) {
        /* Seek. */
        ret = lseek(fd_swapfile, page * PAGE_SIZE, SEEK_SET);

        /* Check that it worked. */
        if (ret == -1) {
            perror("lseek");
            abort();
        }

        /* Save to slot, need to be able to read from page to write to slot. */
        set_page_permission(page, PAGEPERM_READ);
        ret = write(fd_swapfile, page_to_addr(page), PAGE_SIZE);

        /* Check that it worked. */
        if (ret == -1) {
            perror("write");
            abort();
        }
        if (ret != PAGE_SIZE) {
            fprintf(stderr, "write: only wrote %d bytes (%d expected)\n", ret,
                PAGE_SIZE);
            abort();
        }
    }

    /*
     * Step 2:
     * Remove the page’s address-range from the process’ virtual address space.
     */
    ret = munmap(page_to_addr(page), PAGE_SIZE);

    /* Check that it worked. */
    if (ret == -1) {
        perror("munmap");
        abort();
    }

    /*
     * Step 3:
     * Update the page table entry for the page to be “not resident”.
     */
    clear_page_entry(page);


    assert(!is_page_resident(page));
    num_resident--;

    /* Inform the paging policy that the page was unmapped. */
    policy_page_unmapped(page);
}
Exemple #5
0
/* This function maps the specified page from the swap file into the virtual
 * address space, and sets up the page permissions so that accesses and writes
 * to the page can be detected.
 */
void map_page(page_t page, unsigned initial_perm) {
    int ret;

    assert(page < NUM_PAGES);
    assert(initial_perm == PAGEPERM_NONE || initial_perm == PAGEPERM_READ ||
           initial_perm == PAGEPERM_RDWR);
    assert(!is_page_resident(page));  /* Shouldn't already be mapped */

#if VERBOSE
    fprintf(stderr, "Mapping in page %u.  Resident (before mapping) = %u, "
           "max resident = %u.\n", page, num_resident, max_resident);
#endif

    /* Make sure we don't exceed the physical memory constraint. */
    num_resident++;
    if (num_resident > max_resident) {
        fprintf(stderr, "map_page: exceeded physical memory, resident pages "
                "= %u, max resident = %u\n", num_resident, max_resident);
        abort();
    }

    /*
     * Step 1:
     * Add the page’s address-range to the process’ virtual memory.
     * Use the flags MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS to force mmap() to
     * use the specified address, and to use the anonymous file so that the
     * page will initially be filled with zeros.
     */

    /* Use mmap to add to virtual memory. */
    void * vm_address = mmap(page_to_addr(page), PAGE_SIZE,
        pageperm_to_mmap(PAGEPERM_RDWR), MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS,
        -1, 0);

    /* Check that it worked. */
    if (vm_address == (void *) -1) {
        perror("mmap");
        abort();
    }
    if (vm_address != page_to_addr(page)) {
        fprintf(stderr, "mmap: address changed\n");
        abort();
    }

    /*
     * Step 2:
     * Seek to the start of the corresponding slot in the swap file, read the
     * contents into the page.
     */

    /* Seek. */
    ret = lseek(fd_swapfile, page * PAGE_SIZE, (size_t) SEEK_SET);

    /* Check that it worked. */
    if (ret == -1) {
        perror("lseek");
        abort();
    }

    /* Read contents. */
    ret = read(fd_swapfile, page_to_addr(page), (size_t) PAGE_SIZE);

    /* Check that it worked. */
    if (ret == -1) {
        perror("read");
        abort();
    }
    if (ret != PAGE_SIZE) {
        fprintf(stderr, "read: only read %d bytes (%d expected)\n", ret,
            PAGE_SIZE);
        abort();
    }

    /*
     * Step 3:
     * Update the page table entry for the page to be resident, and set the
     * appropriate permissions on the page.
     */
    set_page_resident(page);
    set_page_permission(page, initial_perm);


    assert(is_page_resident(page));  /* Now it should be mapped! */
    num_loads++;

    /* Inform the paging policy that the page was mapped. */
    policy_page_mapped(page);

#if VERBOSE
    fprintf(stderr, "Successfully mapped in page %u with initial "
        "permission %u.\n  Resident (after mapping) = %u.\n",
        page, initial_perm, num_resident);
#endif
}