Implementation Of SachOS(Part7)

Sachithra_Manamperi
5 min readSep 6, 2021

This is the seventh in a series of articles on the topic. I’m following the Reference Book “The little book about OS development” by Erik Helin and Adam Renberg.

Here’s the link to the previous article.👇

If you Haven’t followed the article series Start reading the first article From here👇

Virtual Memory

Virtual memory is created by abstracting physical memory. The goal of virtual memory is to facilitate application development by allowing processes to access more memory than is physically available on the machine. We don’t want programs tampering with the kernel’s or other applications’ memory for security reasons.

In the x86 architecture, virtual memory can be implemented in two ways: segmentation and paging. The most common and versatile strategy is paging, which we will use in the following chapter. Some segmentation is still required to allow code to operate under different permission levels.

Memory management is a significant part of what an operating system does. This is taken care of by paging and page frame allocation.

I discussed segmentation in the previous section of this article.

Virtual Memory Through Segmentation

You could completely avoid paging and rely solely on virtual memory segmentation. Users would have their own segments, each with its own base address and limit. This is the only way a process can see the memory of a different process. Contiguous physical memory for a process is a problem (or at least it is very convenient if it is). A program’s memory requirements must be known in advance (unlikely), or we can move memory segments to areas where they will grow when the limit is reached (expensive, fragmenting, and can result in “out of memory” even when adequate RAM is available). Using paging, both of these problems can be resolved.

Paging

Segmentation converts a logical address into a linear address. These linear addresses are converted to physical locations by paging, which also determines access permissions and how memory should be cached.

x86 processors use paging to enable virtual memory. This is achieved by paging, which gives each process the impression that the available memory is 0x00000000–0x00000000, even though the actual memory space is much smaller. As an added bonus, the virtual (linear) address will be used by the process when accessing memory, instead of the physical address. No changes will be made to the code in the user process (except for execution delays). When the linear address is converted to a logical address, the MMU and the page table are involved. If the virtual address is not mapped to a physical address, the CPU will cause a page fault interrupt.

Page entries.

Because each process has its own set of page mappings, virtual memory regions tend to be independent of one another. There is no way around the 4KB limit in the x86 architecture (32-bit). Description words on each page indicate to the processor on which frame the page should be placed. When it comes to the 32-bit word, the least significant 12 bits are always zero because pages and frames must be aligned on 4KB boundaries (4KB being 0x1000 bytes). So, the architecture makes use of them to keep track of information about the page, such as its existence, whether kernel mode or user mode it is and other such details

Enabling Paging

A page directory’s address is first written to “cr3” and bit 31 of “cr0” is set to 1. It’s possible to use four-MB pages by using the PSE bit “cr4” This assembly code can be used to enable paging.

The Kernel’s virtual address

A very high virtual memory address (such as 0xC0000000) would be ideal for the kernel’s location (3 GB). Only a user-mode process with a size of 3 GB or more can cause a kernel conflict now, and this is the only way. For example, a higher-half kernel uses virtual addresses of up to three gigabytes (GB). To achieve the same results, the kernel can be placed at any address greater than 0xC0000000. How much virtual memory a kernel and a process can use determines which address to use.

Paging provides a virtual memory.

In virtual memory, paging has two advantages. Starting with the ability to fine-tune memory access. Some of the options include marking PL0 pages as read-only, read-write, or exclusive to PL0 only. As a second benefit, it creates the illusion of a single, uninterrupted memory. A user-mode program and the kernel can access the memory as if it were contiguous, and the contiguous memory can be expanded without rearranging data in the memory space However, we don’t need to allocate page frames to pages unless they actually use them. Using this technique, processes can have code around 0x00000000 and a stack slightly below 0xC0000000, while still requiring only two threads to run.
“paging. h” is a header file that contains functions and other information that is required for paging.

So, in the “paging.c” file, we can define those functions in the following manner:

The “makefile” needs to be modified in the following way in order to compile those files correctly.

It’s now time to call the “kmain.c” file’s paging initializing function!

“make run” is now available for running the OS. The “com1.out” file will show “Paging enabled” if you are successful.

I believe you have a solid understanding of user mode. This link will take you to my Github repository.

Thank you for reading, and I’ll be back with Part 08 of this article series next week.

--

--

Sachithra_Manamperi

Undergraduate | Software Engineering | Dharmaraja College Kandy | Sri Lankan