Not logged inTalkContributionsCreate accountLog in

Memory & Paging

From nexOS Wiki
32-bit paging, physical bitmap allocator, framebuffer handling

Outdated “no paging” docs were removed. nexOS now enables paging (CR3 + CR0.PG) with an identity map and a bitmap page allocator (kmalloc/kfree). This page describes the current kernel.c:page_init/mem_init implementation.

Contents

[hide]

Address-space model

logical addr --> [GDT: base 0] --> linear addr --> [paging: identity] --> physical addr
                       flat, 4 GiB, ring 0        CR3 = page_directory, CR0.PG = 1

Segmentation is flat; paging provides the mapping. Low memory is identity-mapped so existing bootloader addresses (0x5000 block, 0x8000 kernel, 0x200000 backbuffer) keep working after CR0.PG is set.

Page tables

kernel.c reserves five 4 KiB-aligned tables:

static u32 page_directory[1024] __attribute__((aligned(4096)));
static u32 pt0[1024], pt1[1024], pt2[1024], pt3[1024];  // 0-16 MiB identity
static u32 pt_lfb[1024];                               // framebuffer window
#define PAGE_SIZE 0x1000
#define NUM_PAGES 4096          // 4096 x 4 KiB = 16 MiB managed
#define HEAP_START_PAGE 1024    // heap starts at 4 MiB
page_init():
  pt0[i] = (i*0x1000) | 0x03;          // 0x000000-0x3FFFFF  present+rw
  pt1[i] = (0x400000 + i*0x1000)|0x03; // 0x400000-0x7FFFFF
  pt2[i] = (0x800000 + i*0x1000)|0x03; // 0x800000-0xBFFFFF
  pt3[i] = (0xC00000 + i*0x1000)|0x03; // 0xC00000-0xFFFFFF
  page_directory[0..3] = pt0..pt3 | 0x03;
  // LFB: if VBE base >= 0x1000000, map 4 MiB window at its 4 MiB-aligned base
  // mov page_directory -> CR3; set CR0 bit 31 (0x80000000)

Flags 0x03 = present + read/write, supervisor only. No user pages, no NX, no PAE. The LFB window is only installed when the framebuffer lives high (typical for VESA linear buffers); low VGA fallback (0xA0000) is already covered by pt0.

Physical allocator

A 512-byte bitmap (mem_bitmap[NUM_PAGES/8]) tracks 4096 pages. Pages below HEAP_START_PAGE (first 4 MiB: kernel, tables, BIOS area) are marked used at boot; the rest is heap.

mem_init(): zero bitmap, mark pages 0..1023 used.
kmalloc(size): pages = ceil(size/4096); first-fit scan from page 1024;
               mark used, return (page * 0x1000). Returns 0 on failure.
kfree(ptr):    unmark single page (caller frees whole pages; no coalescing
               beyond bitmap bits, no free-list).

There is also a tiny snprintf (supports %x %d %s %c) used for terminal and browser status lines. It is freestanding — no libc.

Bootloader parameter block

16 bytes at 0x5000, written by boot.asm, read by vbe_init():

#define VBE_LFB       (*(u32 volatile *)0x5000)
#define VBE_WIDTH     (*(u16 volatile *)0x5004)
#define VBE_HEIGHT    (*(u16 volatile *)0x5006)
#define VBE_PITCH     (*(u16 volatile *)0x5008)
#define VBE_BPP       (*(u8  volatile *)0x500A)
#define VBE_RED_POS   (*(u8  volatile *)0x500B)
#define VBE_GRN_POS   (*(u8  volatile *)0x500C)
#define VBE_BLU_POS   (*(u8  volatile *)0x500D)
OffsetSizeFieldSource
0x004LFB addressModeInfo +0x28
0x042widthModeInfo +0x12
0x062heightModeInfo +0x14
0x082pitchModeInfo +0x10
0x0A1bppModeInfo +0x19
0x0B–0x0D1+1+1R/G/B field positionsModeInfo +0x20/0x22/0x24

Framebuffer & double buffering

Rendering targets an off-screen frame at 0x200000 (BACKBUFFER_ADDR), then blits to the real LFB once per frame to avoid flicker. Recent work added fast fills (32-bit writes for 32bpp) and bulk present.

render_desktop():
  lfb = (u8*)0x200000;  // draw everything to back buffer
  draw_desktop_icons(); draw_window(); draw_terminal(); ...
  for (row < scr_h) memcpy(back+row*pitch -> front+row*pitch);
  lfb = front_lfb;      // restore

Pixel formats

bppEncodingWrite
32 / 24RGB888 (field-position shifted)4-byte fast path (32bpp) or 3 bytes LE
16RGB565u16 at base + x*2
8raw indexbase[x]