Writing an OS Kernel from Scratch – Part 19: User and Kernel Address Space — Building Secure Virtual Memory Boundaries
“All processes share kernel code, but must never peek at each other; user programs roam freely but cannot cross the boundary. Today, we design the higher-half kernel mapping, achieving perfect isolation and efficient sharing of user and kernel address spaces!”
In previous posts, we implemented paging, multi-process, multi-core, but all processes had completely independent page directories — including kernel code, data, and page tables themselves! This caused:
- TLB flush on every process switch (terrible performance)
- Inability to efficiently share kernel resources
- Kernel couldn’t directly access user memory
A real OS must adopt a Higher-Half Kernel design:
✅ Low address space (0x00000000 – 0xBFFFFFFF): User space (independent per process)
✅ High address space (0xC0000000 – 0xFFFFFFFF): Kernel space (shared by all processes)
Why Higher-Half Kernel?
Traditional independent page directory problems:
- TLB frequent flushes → 30%+ performance loss
- Kernel can’t access user memory → complex address translation for syscalls
- Kernel memory waste → kernel code mapped N times (4GB × N processes)
Higher-half kernel advantages:
- TLB friendly: kernel mapping unchanged, no TLB flush on process switch
- Efficient access: kernel can directly access user memory via high addresses
- Memory savings: kernel code/data mapped once
Linux, Windows, macOS all use higher-half kernel design!
Comments