001 Notes
Booting, My Confusions and ChatGPT
Booting Before Normal Memory Exists
1. Boot as Capability Transitions
Power applied
|
v
CPU can fetch first instruction
|
v
Firmware can execute from ROM/flash
|
v
Tiny temporary writable storage exists
|
v
DRAM is initialized
|
v
Assembly prepares a C runtime
|
v
Memory types and caches are configured
|
v
First page tables create virtual memory
|
v
Larger firmware, bootloader, kernel, or OS code can run normally
2. Power-On and First Instruction Fetch
CPU reset
|
| fetch instruction at reset vector
v
+-------------------+ platform decode +------------------+
| CPU fetch address | ---------------------------> | firmware flash |
| near top of space | | ROM/SPI contents |
+-------------------+ +------------------+
3. What Exists Before Firmware Runs?
power-good / reset / clocks
|
v
hardwired reset sequencing and first-fetch control
|
v
built-in decode / micro-op / microcode machinery
|
v
architectural instruction execution
|
v
platform firmware fetched from ROM/flash
hardwired/control logic:
makes reset, first fetch, minimum decode, and low-level sequencing possible
built-in microcode/control store:
helps implement complex architectural behavior inside the CPU
platform firmware:
normal ISA-visible code fetched from ROM/flash
4. Microcode
hardwired reset/control logic
|
v
built-in CPU microcode and internal control store
|
v
firmware instructions fetched from ROM/flash
CPU built-in microcode
|
v
Firmware may apply update
|
v
Bootloader or kernel starts
|
v
OS may apply early update
|
v
Late runtime updates require more coordination
5. Execution Without RAM
Before DRAM init
Instruction fetch:
CPU ---> firmware ROM/flash works
Writable data:
CPU ---> DRAM not safe yet
CPU ---> stack in DRAM not safe yet
CPU ---> globals in DRAM not safe yet
6. Cache-As-RAM
before DRAM:
ROM/flash -> instruction fetch
CPU cache -> temporary stack / heap / small globals
DRAM -> not initialized yet
normal cache:
cache miss or eviction may access backing DRAM
cache-as-RAM:
cache must behave like the backing store
eviction to uninitialized DRAM must not happen
reset / first firmware code
|
v
enable CAR using vendor-specific CPU setup
|
v
use CAR for early stack and temporary objects
|
v
initialize DRAM
|
v
copy or discard CAR-resident state
|
v
move stack to DRAM
|
v
tear down CAR
7. XIP: Execute In Place
XIP firmware image
+-----------------------+ fetch +-----+
| ROM / flash | ----------------> | CPU |
| | +-----+
| .text executable |
| rodata readable |
| .data load image | -- must copy --> RAM before normal C use
| .bss no bytes stored | -- must zero --> RAM before normal C use
+-----------------------+
8. Bringing Up DRAM
ROM/XIP execution
|
v
temporary memory or cache-as-RAM
|
v
DRAM controller initialized
|
v
stack moved to DRAM
|
v
next stage loaded/copied/decompressed into DRAM
|
v
temporary memory retired
9. Preparing to Call C
Firmware image in ROM/flash Runtime layout in RAM
+----------------------+ +----------------------+
| .text | execute in place | optional .text copy |
| .rodata | -----------------> | optional .rodata copy |
| .data initial bytes | ---- copy --------> | .data writable |
| no .bss bytes | ---- zero --------> | .bss zeroed |
+----------------------+ | stack |
| heap later, maybe |
+----------------------+
static int global_counter;
10. Segmentation, Descriptor Tables, and Early Faults
11. Memory Types: MTRR, PAT, Caches, and MMIO
Physical address space
+----------------------+ cacheable WB ordinary DRAM
| RAM |
+----------------------+ UC or WP firmware ROM/flash window
| ROM / flash alias |
+----------------------+ UC device registers
| MMIO |
+----------------------+ WC or UC framebuffer
| framebuffer |
+----------------------+
12. The First Page Tables
Before paging:
CPU address used by instruction fetch
|
v
physical address directly
After paging:
virtual address
|
v
page-table walk
|
v
physical address
physical RAM holds page tables
|
v
load page-table root register
|
v
enable paging
|
v
CPU begins translating instruction fetches through page tables
13. Example: Converting VA to PA
VA base: 0xffffffff81000000
PA base: 0x0000000000100000
VA: 0xffffffff81001234
PA: 0x0000000000101234
VA = 0xffffffff81001234
63 48 47 39 38 30 29 21 20 0
+----------------------+----------+----------+----------+---------------+
| sign extension | PML4 idx | PDPT idx | PD idx | 2 MiB offset |
+----------------------+----------+----------+----------+---------------+
PML4 index = 511 = 0x1ff
PDPT index = 510 = 0x1fe
PD index = 8 = 0x008
2 MiB offset = 0x1234
CR3
|
v
PML4 table
entry[511] --> PDPT physical address
|
v
PDPT table
entry[510] --> PD physical address
|
v
PD table
entry[8] --> PA base 0x00100000
flags: present, writable,
executable, PS=1
page size: 2 MiB
physical address = leaf physical base + page offset
physical address = 0x00100000 + 0x1234
physical address = 0x00101234
0xffffffff81001234 ---> 0x0000000000101234
14. Same Example With 4 KiB Pages
VA = 0xffffffff81001234
63 48 47 39 38 30 29 21 20 12 11 0
+----------------+-------+-------+-------+-------+-----------+
| sign extension | PML4 | PDPT | PD | PT | 4K offset |
+----------------+-------+-------+-------+-------+-----------+
PML4 index = 511 = 0x1ff
PDPT index = 510 = 0x1fe
PD index = 8 = 0x008
PT index = 1 = 0x001
4K offset = 0x234
CR3
|
v
PML4[511] -> PDPT physical page
|
v
PDPT[510] -> PD physical page
|
v
PD[8] -> PT physical page
|
v
PT[1] -> PA base 0x00101000
flags: present, writable, etc.
physical address = 0x00101000 + 0x234
physical address = 0x00101234
2 MiB page:
leaf base = 0x00100000
offset = 0x00001234
result = 0x00101234
4 KiB page:
leaf base = 0x00101000
offset = 0x00000234
result = 0x00101234
15. Pseudocode for Forcing a Mapping
map_2m(va_base, pa_base, flags):
assert va_base is 2 MiB aligned
assert pa_base is 2 MiB aligned
pml4_i = bits(va_base, 47, 39)
pdpt_i = bits(va_base, 38, 30)
pd_i = bits(va_base, 29, 21)
pml4 = physical_address_from_cr3()
pdpt = ensure_physical_page_table(pml4[pml4_i])
pd = ensure_physical_page_table(pdpt[pdpt_i])
pd[pd_i] = pa_base
| PRESENT
| WRITABLE
| PAGE_SIZE_2M
| flags
make_cpu_observe_page_table_update()
16. TLB and Mapping Transition Caveats
old mapping in TLB
|
| page table memory is changed
v
CPU may still use old translation
|
| invalidate / serialize correctly
v
CPU observes new translation
Before enabling paging:
instruction pointer names a physical execution path
After enabling paging:
instruction pointer is interpreted through paging
Therefore:
the next instruction fetch must be mapped correctly
17. Debugging Before There Is a System
No RAM yet -> registers, POST codes, hardware trace
UART ready -> serial bytes
Temp RAM ready -> tiny trace buffer
DRAM ready -> larger logs
Paging ready -> virtual-address-aware diagnostics
OS ready -> normal logging
Comments