Build your own OS (part 7)

Pasan Devin Jayawardene
4 min readSep 6, 2021

--

Virtual memory & Paging

image by Katemangostar on freepik.com (https://www.freepik.com/free-vector/business-people-working-laptop-development_4332351.htm#page=1&query=software&position=1)

Hello and welcome everyone to the seventh instalment of my OS development article series. We already have implemented a considerable part of our OS with previous articles (I’ll include the links to those at the end), and In this article, I’ll show you how to implement virtual memory into our operating system via paging.

What is virtual memory?

Virtual memory is a feature of an operating system that allows a computer to compensate for physical memory shortages by transferring data pages from random access memory to disk storage. This is a temporary process that is designed to work as a combination of RAM and hard disk space.

This means that when RAM becomes insufficient, virtual memory can move data from it to a space known as a paging file. This procedure frees up RAM so that a computer can complete the task.

We can accomplish virtual memory in two ways. They are,

  1. Segmentation &
  2. Paging.

Since we discussed and implemented segmentation in the 4th article, we will now focus on paging.

Paging

Paging is the most common method for enabling virtual memory in x86 architecture. Virtual memory via paging means that each process will have the impression that the available memory range is 0x00000000–0xFFFFFFFF, even if the actual memory size is much smaller. This also implies that when a process addresses a byte of memory, it will use a virtual (linear) address rather than a physical one.

A birdseye view of paged memory: The OS allows each program to think it has all the memory to itself

The Memory Management Unit (MMU) and the page table convert the linear address to a physical address. If the virtual address is not mapped to a physical address, the CPU will raise a page fault interrupt.

Operating system maintains a table about which logical location maps to physical locations

Enable paging

To enable paging, first write the address of a page directory to cr3 and then set bit 31 (the PG “paging-enable” bit) of cr0 to 1. Set the PSE bit (Page Size Extensions, bit 4) of cr4 to use 4 MB pages.

An example is shown in the assembly code below:

Placing the kernel

Now we need to place the kernel at a virtual memory address. To begin, it is preferable to place the kernel at 0xC0100000 (above 3GB). This maps the entire memory range (0x00000000, “size of kernel”) to the range (0xC0000000, 0xC0000000 + “size of kernel”).

When the kernel uses virtual addresses of 3 GB or more, it is referred to as a higher-half kernel. To accomplish this, we can modify the linker script as follows:

Higher half linker script

Entering the kernel

There is no paging table when GRUB enters kernel code. As a result, all references to 0xC0100000 + X will not be mapped to the correct physical address, resulting in a general protection exception (GPE) at best, and a crash at worst (if the computer has more than 3 GB of memory).

As a result, assembly code that does not make use of relative jumps or relative memory addressing must be used to perform the following tasks:

  • Create a page table
  • Identity map (mapping each virtual address onto the same physical address) the first 4 MB of virtual address space.
  • Add an entry for 0xC0100000 that corresponds to 0x0010000.

Following the creation of the table, a jump to a label can be performed to make register eip point to a virtual address in the upper half:

The register eip will now point to a memory location somewhere after 0xC0100000, and all code will now execute as if it were located at 0xC0100000, the higher-half.

That’s it for today’s article. I’ll put the link to my Github repo at the end if you still have doubts about the implementation. I’ll meet you again with another interesting article. Until then, stay safe & Goodbye!

Image from Harry Potter movie

-Pasan Devin Jayawardene-

Reference: The little book about OS development (Erik Helin, Adam Renberg)

Github Repo:

Previous articles:

--

--