Updated on 30 Mar, 202624 mins read 34 views

The Physical Memory Manager (PMM) is one of the most foundational components is OS development. It operates at the lowest level of memory management, dealing directly with phsyical RAM, not abstraction like virtual memory.

Before any advanced features like processes, paging, or heaps can exist, the OS must answer a simple but critical question:

Which parts of RAM are safe to use, and how do we manage them efficiently?

That is exactly what the PMM is responsible for.

What is the Physical Memory Management?

The Physical Memory Manager (PMM) is responsible for:

  • Tracking which parts of RAM are free or used
  • Allocating and freeing physical memory blocks (frames/pages)
  • Providing memory to:
    • Kernel
    • Virtual Memory Manager (VMM)
    • Devices drivers (DMA, buffers, hardware interaction)

Important Note

The PMM does not manage memory byte-by-byte.

Instead, it operates on fixed-size blocks called:

  • Frames (physical memory)
  • Pages (virtual memory)

Basic Unit:

Physical memory is dividied into fixed-size blocks:

  • On x86:
    • Page size = 4096 bytes (4 KB)
  • Called:
    • Frames (physical)
    • Pages (virtual)

Example:

If your system has 4 GB RAM.

Then

4GB / 4KB = 1,048,576 frames

Each frame represents a single allocatable unit.

Memory Layout at Boot

When the OS boots, RAM is not entirely free.

Some regions are already occupied:

  • Kernel code/data
  • Bootloader
  • BIOS/UEFI structures
  • Reserved hardware regions (MMIO, ACPI, etc.)

Example Memory Map (BIOS E820):

From BIOS (e.g., via E820):

0x00000000 - 0x0009FC00  β†’ Usable
0x0009FC00 - 0x000A0000  β†’ Reserved
0x00100000 - 0x7FFFFFFF  β†’ Usable

Key Responsibility of PMM

The PMM must:

  • Parse this memory map
  • Identify usable regions
  • Avoid reserved areas
  • Build an internal structure to manage memory

Memory Map: Bootloader's Role

The OS does not directly discover memory – it relies on the bootloader.

BIOS Memory Detection (E820)

The most reliable method is:

int 0x15, eax = 0xE820

This returns a list of memory regions, each with:

  • Base address
  • Size
  • Type

Memory Region Types

TypeMeaning
1Available (usable RAM)
2Reserved
3+ACPI / firmware / special

Bootloader Responsibilities

The bootloader:

  1. Iteratively calls BIOS (E820)
  2. Builds a memory map
  3. Stores it in memory
  4. Passes to kernel:
    1. Pointer to memory map
    2. Entry count
    3. Total memory size

Critical Insight

This becomes the contract between bootloader and kernel.

If this data is wrong – your OS will break.

Why Do We Need a Physical Memory Manager?

When your OS boots, memory is:

  • Partially used (kernel, BIOS, bootloader)
  • Reserved hardware regions
  • Fragmented
  • Unstructured

The bootloader gives us a memory map, but that's just information, not a management system.

Without a PMM:

  • You might overwrite your kernel
  • Allocate the same memory twice
  • Corrupt hardware-mapped regions

So, PMM must answer:

  • Which pages are free?
  • Which pages are reserved?
  • How do I allocate contiguous memory?
  • How do I avoid overwriting critical regions?

Data Structures for PMM

There are different ways on how to handle a PMM.

This is where design choices matter:

1 Bitmap (Most Common)

Concept:

Each frame is represented by 1 bit:

  • 0 : free
  • 1 : used

This is the simplest approach: one bit per page frame, where 0 = free and 1 = allocated. For a 4GiB machine (1,048,576 pages), this costs just 128 KB of RAM – negligible.

0 β†’ free
1 β†’ used (allocated)

Example:

Frame:  0 1 2 3 4 5 6 7
Bitmap: 1 0 0 1 1 0 0 0

Memory Cost

For 4 GB RAM:

1,048,576 frames β†’ 1,048,576 bits β†’ 128 KB

Very efficient.

Allocations:

Allocation is O(n) in the worst case – you must scan until you find a zero bit.

Freeing is O(1): just clear the bit.

  • Scan for first 0
  • Mark it 1

Pros:

  • Very space efficient, 1 bit per 4 KB
  • Simple
  • Easy to debug

Cons:

  • Slow for large memory (linear scan)
  • Hard to find contiguous blocks efficiently

Complexity:

OperationTime
AllocateO(n)
FreeO(1)

2 Free List

Maintain a linked list of free frames.

Pos:

  • Fast allocation
  • Easy to implement

Cons:

  • Poor for large contiguous allocation
  • Fragmentation issues

3 Buddy Allocator (Advanced)

Splits memory into power-of-2 blocks:

1 page, 2 pages, 4 pages, 8 pages...

Pros:

  • Efficient merging (coalscing)
  • Good for contiguous memory

Cons:

  • More complex
  • Internal Fragmentation

Core Design: Bitmap-Based PMM

We would use a bitmap-based allocator.

Concept:

Divide memory into fixed-size pages (usually 4 KB):

Physical Memory β†’ [Page0][Page1][Page2]...[PageN]

Then track each page with a bit:

Bitmap β†’ 1 0 1 0 0 1 ...
         ↑ ↑ ↑ ↑ ↑ ↑
         Used/Free

Bitmap tracks:

  • 1: allocated
  • 0 : free

Memory Representation:

Physical memory is divided into:

Frame 0 β†’ 0x00000000
Frame 1 β†’ 0x00001000
Frame 2 β†’ 0x00002000
...

Each frame:

  • Size = PAGE_SIZE (usually 4096 bytes)

Bitmap Structure

A bitmap is stored in memory:

Bit index = Frame number

Example:

FrameBitStatus
01Used
10Free
21Used

Initialization Strategy

The PMM follows a safe-first initialization model:

Step 1: Assume All Memory is Used

The bitmap is initialized to:

111111111111111111...

This ensures:

  • No accidental use of invalid memory
  • No use of unknown memory

Step 2: Free Valid Memory Regions

The kernel iterates over the bootloader-provded memory map:

  • For each region of type available (type = 1)
    • Corresponding bits are cleared
if (region.type == USABLE)
    mark as free

Result:

Used β†’ Reserved regions
Free β†’ Usable RAM

Step 3: Reserve Critical Regions

Even if marked β€œavailable”, certain regions must remain reserved:

  • Kernel image
  • Kernel stack
  • Memory bitmap itself
  • Low memory regions (BIOS / hardware)
  • Null page (0x0)

Allocation Model

1 Single Page Allocation

  1. Scan bitmap
  2. Find free bit
  3. Mark as used
  4. Return physical address

2 Contiguous Allocation

Needed for:

  • DMA
  • Page tables
  • Large buffers

Algorithm:

  • Find N consecutive free bits
  • Mark all as used

Bootloader Input

The OS receives a memory map:

[Base Address | Size | Type]

Types:

TypeMeaning
1Usable RAM
OthersReserved

Key Design Principle

A robust PMM does:

Assume all memory is unsafe -> explicitly mark safe regions as usable.

This avoids accidental corruption of critical memory.

How Memory Looks Physically

Let's take a concrete example.

Assume

  • Total RAM = 64 KB
  • Page size = 4 KB
64 KB / 4 KB = 16 frames

Frame Layout

FrameAddress
00x0000
10x1000
20x2000
......
150xF000

Bitmap Representation

Since:

1 frame = 1 bit
16 frames = 16 bits = 2 bytes
Initial Bitmap (after memset 0xFF)
11111111 11111111

Means:

All memory is USED (reserved)

What Happens During Initialization

Step 1: Everything marked USED

memset(MemoryBitmap, 0xFFFFFFFF, MemoryBitmapSize);

Bitmap:

11111111 11111111

Step 2: BIOS says usable region

Example:

Usable: 0x1000 β†’ 0x9000

Frames:

Frame 1 β†’ Frame 8

Step 3: MMFreeRegion()

MmMemoryMapUnsetBit(Frame++);

Bit-by-bit change

Before:

Frame:   0 1 2 3 4 5 6 7 8 9 ...
Bitmap:  1 1 1 1 1 1 1 1 1 1 ...

After freeing 1-8:

Frame:   0 1 2 3 4 5 6 7 8 9 ...
Bitmap:  1 0 0 0 0 0 0 0 0 1 ...

Now:

  • 0 : free
  • 1 : reserved

How Bitmap is Stored in Memory

unintptr_t *MemoryBitmap;

Assume:

  • __BITS = 32 (32-bit system)

So each entry stores 32 frames.

Example:

MemoryBitmap[0] β†’ frames 0–31
MemoryBitmap[1] β†’ frames 32–63

Suppose:

MemoryBitmap[0] = 0b11101111

Expanded:

BitFrameValue
0Frame 01 (used)
1Frame 11
2Frame 21
3Frame 31
4Frame 40 (free)
5Frame 51
6Frame 61
7Frame 71

 

Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *