summaryrefslogtreecommitdiff
path: root/doc/boot/kernel_address.md
blob: c7449fcb6f1eaad9128a50d04e84a261ebb96228 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Kernel address
Kernel address is place in RAM, where kernel is located. (for example uefi can place kernel to it)


## x86_64
0x100000 (1MiB)
On x86, the first 1MiB of physical memory is a minefield of legacy hardware reservations dating back to the orignal IBM PC (1981):
0x00000000 - 0x000003FF    IVT (Interrupt Vector Table) — real mode
0x00000400 - 0x000004FF    BIOS Data Area
0x00000500 - 0x00007BFF    Conventional memory (usable, but tiny)
0x00007C00 - 0x00007DFF    Boot sector load address (BIOS legacy)
0x00007E00 - 0x0007FFFF    More conventional memory
0x00080000 - 0x0009FFFF    EBDA (Extended BIOS Data Area)
0x000A0000 - 0x000BFFFF    VGA video memory (framebuffer)
0x000C0000 - 0x000C7FFF    VGA BIOS ROM
0x000C8000 - 0x000EFFFF    Other option ROMs
0x000F0000 - 0x000FFFFF    System BIOS ROM
─────────────────────────────────────────────────
0x00100000                 FIRST SAFE ADDRESS (1 MiB)

0x00100000 is the first address above all this legacy garbage. It's whene Linux loads its kernel too ("high memory" region).
Because of using UEFI (and not current support of BIOS) i don't need all this fields.

## AArch64
0x40100000
AArch64 has no legacy baggage - theere's no fixed memory map baked into the arch (i think it's one of the problem of this arch). 
Instead of it each board/machine defiens where RAM starts. For QEMU's virt machine (that i use for first time: qemu-system-aarch64 -machine virt) RAM begins:
0x00000000 - 0x3FFFFFFF    Device MMIO region (GIC, UART, virtio, flash, etc.)
─────────────────────────────────────────────────
0x40000000              RAM starts here on QEMU virt

Technically i can succesfully use 0x40000000 as the first byte, but i need to add 1MiB offset for the UEFI firmware's own use (page tables, runtime services data, memory map and other). The UEFI firmware itself is loaded into early RAM and may have data structs there.

On a real AArch64 hrdware RAM starts a completely different address (for exmaple at 0x0 on the Pi). That's why we need to read device tree blob or UEFI memory map to figure out where RAM actually is, rather than hardcoding.


## Future solutions

Right now kernel is identity-mapped (virtual == phisical), so the linker script address must match where the kernel phiscyally lives. Once we implement higher-half mapping in next Developing Phase (Phase II), the picture must changes:

Current (identity-mapped):
    Linker says 0x100000, loaded at 0x100000, runs at 0x100000

After higher-half (Phase 2):
    Linker says 0xFFFFFFFF80100000  (virtual, higher-half)
    Loaded at   0x100000            (physical, by EFI loader)
    Page tables map virtual → physical
    Kernel runs at its virtual address


At that point, the physical load address becomes flexible - the ELF loader can use AllocateAnyPages and the page tables handle the translation. The linkes script address becomes the virtual address, and the two are decoupled.
Linux works exactly this way: vmlinux is linked at a high virtual address like 0xFFFFFFFF81000000, but it's physically loaded wherever the bootloader puts it.