This page does not represent the most current semester of this course; it is present merely as an archive.

Implement a page table structure in C, with associated access functions.

1 Specification

We supply two header files.

1.1 config.h

config.h does nothing other than #defineing two constants.

Your code must use these constants, must not redefine them, and must continue to work even if we change their values. For example, if we compile with a different config.h that #defines LEVELS as 3 instead of 4, your code should create a 3-level page table instead of a 4-level page table. Your code should work for all integer values of LEVELS between 1 and 6 inclusive and all integer values of POBITS between 4 and 18 inclusive. As an exception, it does not need to (but may) support cases where (POBITS − 3) × (LEVELS + 1) > 60.

1.2 mlpt.h

mlpt.h defines the public API your code will use. You are welcome to edit it, provided such edits will not cause testing code to fail to compile.

1.3 Behavior

Prior to the first invocation of page_allocate, ptbr should be NULL; thereafter it should be a pointer to a heap-allocated array, cast as a size_t. It should not change after the first page_allocate invocation.

If ptbr is not NULL, it should point to an array of size_ts occupying 2POBITS bytes. Each such size_t should be interpreted as a page table entry.

Some texts refer to a PTBR containing a physical address; others to it containing a physical page number. The above definition asserts it contains a physical address, not page number. As such, it will always have 0 in its low-order POBITS bits.

Each page table entry should be either

0 in the low-order bit

There is no physical page.

The remaining bits have no defined meaning; you may use them however you wish.

PTE 0x1234567812345678 has a zero in the low-order bit, and thus indicates the absence of a physical page.

1 in the low-order bit

The bits above the POBITS low-order bits are the physical page number of either the next level page table or the physical page of memory. The POBITS − 1 low-order bits (excluding the 1 in the lowest-order bit) have no defined meaning; you may use them however you wish.

PTE 0x1234567812345679 has a one in the low-order bit, and thus indicates the presence of a physical page or another level page table. If POBITS is 12, the physical page number (of the page or next page table level) is 0x1234567812345.

No pages should be allocated unless requested by a call to page_allocate.

2 Submission

You should submit code, with a Makefile, that

  • Will work if I move the given mlpt.h and config.h into the directory with them, overwriting those you submit (if any)
  • Meets all above specifications

Because we require no main function, you are welcome to have a target to build a program or not, at your preference. We’ll test by compiling adding our own tester program, though, so if you do have a main make sure it is not in a file required to build your code (i.e., keep main in a different file than your implementations of translate, page_allocate, and ptbr).

3 Tips

To test your code, you’ll likely have to add extra code to let you measure things like the number of pages allocated.

A tip for good functional design: if you can describe what a non-trivial piece of code is doing, make it its own function with that action as its name. I’d encourage having names for all of the steps of address translation that we discussed in lectures.

Since we haven’t used posix_memalign before and it’s manual page is a bit confusing, the code I used to use it was

You will likely find yourself casting between size_t and various pointer types multiple places in your code.