Build your own operating system #8_page_frame_allocation

Sadisha Nimsara
5 min readSep 10, 2021

Welcome to the 8th article of this article series. In this article, we are going to discuss about Page Frame Allocation. In previous article, we discussed about how you can implement virtual memory into your operating system.

Lets Go…

First of all; Do you know what is the role of the Page Frame Allocator? It is letting the operating system know that which parts of the memory are free to use.

Managing Available Memory

This first thing we need to know is how much memory is available on the computer the OS is running on.

How much memory is there?

The most effortless approach to do this is to peruse it from the multiboot structure passed to us by GRUB. GRUB gathers the data we need about the memory — what is held, I/O planned, read-just, and so forth We should likewise ensure that we don’t check the piece of the memory utilized by the kernel as free (since GRUB doesn’t stamp this memory as saved). One approach to know how much memory the kernel utilizes is to trade names toward the start and the finish of the kernel paired from the linker script:

ENTRY(loader)   /* the name of the entry symbol */

. = 0xC0100000 /* the code should be relocated to 3 GB + 1 MB */

/* these labels get exported to the code files */
kernel_virtual_start = .;
kernel_physical_start = . - 0xC0000000;

/* align at 4 KB and load at 1 MB */
.text ALIGN (0x1000) : AT(ADDR(.text)-0xC0000000)
{
*(.text) /* all text sections from all files */
}

/* align at 4 KB and load at 1 MB + . */
.rodata ALIGN (0x1000) : AT(ADDR(.rodata)-0xC0000000)
{
*(.rodata*) /* all read-only data sections from all files */
}

/* align at 4 KB and load at 1 MB + . */
.data ALIGN (0x1000) : AT(ADDR(.data)-0xC0000000)
{
*(.data) /* all data sections from all files */
}

/* align at 4 KB and load at 1 MB + . */
.bss ALIGN (0x1000) : AT(ADDR(.bss)-0xC0000000)
{
*(COMMON) /* all COMMON sections from all files */
*(.bss) /* all bss sections from all files */
}

kernel_virtual_end = .;
kernel_physical_end = . - 0xC0000000;

After that, these labels can directly be read from assembly code and pushed on the stack to make them available to C code:

    extern kernel_virtual_start
extern kernel_virtual_end
extern kernel_physical_start
extern kernel_physical_end

; ...

push kernel_physical_end
push kernel_physical_start
push kernel_virtual_end
push kernel_virtual_start

call kmain

This way we get the labels as arguments to kmain. If you want to use C instead of assembly code, one way to do it is to declare the labels as functions and take the addresses of these functions:

void kernel_virtual_start(void);

/* ... */

unsigned int vaddr = (unsigned int) &kernel_virtual_start;

In the event that you use GRUB modules you need to ensure the memory they use is set apart as held also.

Note that the accessible memory shouldn’t be adjoining. In the initial 1 MB there are a few I/O-planned memory areas, just as memory utilized by GRUB and the BIOS. Different pieces of the memory may be comparatively inaccessible.

It’s helpful to partition the memory segments into complete page frames, as we can’t plan part of pages into memory.

Managing Available Memory

How do we realize which page frames are being used? The page frame allocator needs to monitor which are free and which aren’t. There are a few different ways to do this: bitmaps, connected records, trees, the Buddy System (utilized by Linux) and so forth For more data about the various calculations see the article on OSDev.

Bitmaps are very simple to carry out. The slightest bit is utilized for each page casing and (at least one) page frames are committed to store the bitmap. (Note that this is only one approach to do it, different plans may be better or potentially more amusing to execute.)

How Can We Access a Page Frame?

The page frame allocator returns the actual beginning location of the page frame. This page frame isn’t planned in — no page table focuses to this page frame. How might we peruse and compose information to the casing?

We need to plan the page frame into virtual memory, by refreshing the PDT and additionally PT utilized by the kernel. Consider the possibility that all accessible page tables are full. Then, at that point we can’t plan the page frame into memory, since we’d need another page table — which takes up a whole page frame — and to keep in touch with this page frame we’d need to plan its page frame. Somehow this round reliance should be broken.

One arrangement is to hold a piece of the principal page table utilized by the kernel (or some other higher-half page table) for briefly planning page casings to make them open. In the event that the kernel is planned at 0xC0000000 (page catalog section with record 768), and 4 KB page frames are utilized, then, at that point the kernel has somewhere around one page table. In the event that we accept — or restrict us to — a kernel of size all things considered 4 MB less 4 KB we can commit the last passage (section 1023) of this page table for transitory mappings. The virtual location of pages planned in utilizing the last section of the kernel’s PT will be:

(768 << 22) | (1023 << 12) | 0x000 = 0xC03FF000

After we’ve briefly mapped the page frame we need to use as a page table, and set it up to map in our first page frame, we can add it to the paging directory, and eliminate the transitory mapping.

A Kernel Heap

We’ve simply had the option to work with fixed-size information or crude memory as of recently. We can execute malloc and free to use in the kernel since we have a page frame allocator. The main change we need to do is to conjure the page frame allocator rather than sbrk/brk when additional memory is required. The page frames given by the page frame allocator should likewise be mapped to virtual addresses. When sufficiently large blocks of memory are freed, a good implementation should also return page frames to the page frame allocator on call to free.

Further reading

If you are interested in this section, and want to read more about it? Click Here.

Catch you in the next article.

Thank you..!

--

--