The first concern of OS161 virtual memory system is how to manage physical pages. Generally, we can pack a physical page's information into a structure (called struct coremap_entry) and use this struct to represent a physical page. We use an array of struct coremap_entry to keep all physical pages information. This array, aka, coremap, will be one of the most important data structure in this lab.

What should we store in coremap entry structure?

For each physical page, we want to know:

  • Where is this page mapped? (For swapping)
  • What's this pages status? (free, fixed, clean, dirty...)
  • Other info (e.g. need by paging algorithm)

A page can have for different states, as shown below.

This diagram is quite clear. Several points to note:

  • When a physical page is first allocated, its state is DIRTY, not CLEAN. Since this page do not have a copy in swap file (disk). Remember that in a virtual memory system, memory is just a cache of disk.

  • For some reason, we may want to always keep a certain page in memory, e.g.

    • kernel pages, since these pages are direct mapped.
    • user stack and code segment pages which we already knew will be frequently accessed.

So we have a special state called "fixed", means that we'll never swap out these pages to disk.

Coremap Initialization

We need to initiate our coremap in vm_bootstrap. First, we need to find out how many physical pages in system. We can do this using ram_getsize. There is a big trick here. Since we will only know the physical page number, i.e. coremap array length at runtime, so we'd better just define a struct coremap_entry pointer and allocate the actually array at runtime after we got the physical page number, rather than use a statically defined array with some MACRO like MAX_PHY_PAGE_NUM. So at first glance, we may write:

But the above code will definitly fail.

Take a look at ram_getsize, we can see that this function will destroy its firstaddr and lastaddr before return. So after that, if we call kmalloc, which call alloc_kpage, get_ppages and ram_stealmem to get memory, ram_stealmem will fail. The contradiction is: we need to call ram_getsize to get physical page number so that we can allocate our coremap(pages), but once we call ram_getsize we will not be able allocate any pages!

To resolve this contradiction, on one hand, we should initialize all other data structures, e.g., locks, before we call ram_getsize. Then we call ram_getsize to get firstaddr and lastaddr. After that, instead of using kmalloc, we must allocate our coremap manually, without invoking any other malloc routines. A possible solution may be:

Now we allocated our core map just between firstaddr and freeaddr, and [freeaddr, lastaddr] will be system's free memory.

Then we initialize the coremap array, we need to mark any pages between [0, freeaddr) as fixed, since this memory contains important kernel code and data, or memory mapped I/Os. And we just mark pages between [freeaddr, astaddr] as free.

At the end of vm_bootstrap, we may want to set some flags to indicate that vm has already bootstrapped, since functions like alloc_kpages may call different routines to get physical page before and after vm_bootstrap.