cabinet

Cabinet

Submission

As with previous assignments, we wil be using GitHub to distribute skeleton code and collect submissions. Please refer to our Git Workflow guide for more details. Note that we will be using multiple tags for this assignment, for each deliverable part.

For students on ARM Mac computers (e.g. with M1 chip): if you want your submission to be built/tested for ARM, you must create and submit a file called .armpls in the top-level directory of your repo; feel free to use the following one-liner:

cd "$(git rev-parse --show-toplevel)" && touch .armpls && git add .armpls && git commit -m "ARM pls"

You should do this first so that this file is present in all parts.

Code Style

There is a script in the skeleton code named run_checkpatch.sh. It is a wrapper over linux/scripts/checkpatch.pl, which is a Perl script that comes with the linux kernel that checks if your code conforms to the kernel coding style.

Execute run_checkpatch.sh to see if your code conforms to the kernel style – it’ll let you know what changes you should make. You must make these changes before pushing a tag. Passing run_checkpatch.sh with no warnings and no errors is required for this assignment.

Skeleton code setup

Kernel system call stubs

In addition to the pristine Linux kernel source tree (now under linux/) we’ve provided a patch file which will create the syscall stubs for you. You will need to apply this patch to your repo.

The patch is under the following path:

patch/ikea.patch

You can use git apply to apply this patch. First, check which files will be modified by the patch:

$ git apply --stat patch/ikea.patch

You should also inspect what the patch is doing by reading the diffs inside. Finally, you can apply the patch with the following:

$ git apply patch/ikea.patch

Now, when you run git status, you should see some files modified, as well as some .c and .h files added. After verifying that these changes worked as intended, commit them.

Building your patched kernel

Build your kernel. Make sure you’re building with a local version that is different from your fallback (-cs4118), so you don’t overwrite it; set your local version to your UNI (i.e. -<uni>-HW7).

Now, when you build your kernel, you should have the inspect_cabinet() syscall stub in your kernel.

Installing kernel headers

The syscall you will implement has a struct pointer as a parameter. This means that the struct definition needs to be available in both kernel and user land. You’ll need to install the cabinet header (include/uapi/linux/cabinet.h) from the kernel source tree to userspace.

Once you’ve built your cabinet-stubbed kernel, run the following command:

# make headers_install INSTALL_HDR_PATH=/usr

This command will install the headers found under include/uapi/ in your Linux source tree into /usr/include/. Now you should be able to #include <linux/cabinet.h> from userspace! Try compiling the tester program (see below) to make sure this works.

Cabinet, a Memory Inspection Utility

For this assignment, you will be implementing inspect_cabinet(), a system call that allows you to inspect the physical memory associated with a given virtual address of some process. The syscall number for inspect_cabinet() is 505, and it should be implemented as a dynamically loadable module.

Behavior

The function prototype for inspect_cabinet() is the following:

long inspect_cabinet(pid_t pid, unsigned long vaddr, struct cab_info *inventory);

inspect_cabinet() will take in three arguments:

inspect_cabinet() will report the following information about the process:

This information will be used to populate a struct cab_info in userspace (pointed to by inventory), which is defined as follows:

struct cab_info {
        unsigned long paddr;            /* the physical address the virtual address is mapped to */
        unsigned long pf_paddr;         /* the physical address of its page frame */
        unsigned long pte_paddr;        /* the physical address of its PTE */
        unsigned long pmd_paddr;        /* the physical address of its PMD */
        unsigned long pud_paddr;        /* the physical address of its PUD */
        unsigned long p4d_paddr;        /* the physical address of its P4D */
        unsigned long pgd_paddr;        /* the physical address of its PGD */
        int dirty;                      /* 1 if dirty, 0 otherwise */
        int refcount;                   /* number of processes sharing the physical address */
};

Return values and error handling

Testing

Cabinet inspector

We’ve also provided some test programs to help you test your implementation, under the following path:

user/test/cabinet_inspector/

In particular, the cabinet_inspector will execute your syscall, as well as perform a similar lookup using pagemap (from the /proc/ filesystem) as a point of reference. You should make sure that the information from /proc/<pid>/pagemap is consistent with the information reported by your implementation of inspect_cabinet().

You may also find mmapper useful for mapping files into memory and finding their virtual address.

See the README.txt in that directory for detailed usage instructions.

Here are some example shell sessions of testing with cabinet_inspector:

Tips

Deliverables

Submission

To submit this assignment, push the hw7handin tag with the following:

$ git tag -a -m "Completed hw7." hw7handin
$ git push origin master
$ git push origin hw7handin

Useful Resources

Below is some online reading material that you may find helpful for this assignment:


Acknowledgments

The Cabinet assignment and reference implementation were designed and implemented by the following TAs of COMS W4118 Operating Systems I, Spring 2017, Columbia University:

The Cabinet assignment and test harness were updated by the following TAs of COMS W4118 Operating Systems I, Spring 2018, Columbia University:

The Cabinet assignment and test harness were updated by the following TAs of COMS W4118 Operating Systems I, Spring 2020, Columbia University:


Last updated: 2021-11-24