feat: docs & ARCH 2.2, 2.3, 2.4

This commit is contained in:
Faynot
2026-07-07 16:40:41 +03:00
parent c092a81331
commit 1bfde637d0
50 changed files with 5113 additions and 1823 deletions

151
kernel/docs/boot/linker.md Normal file
View File

@@ -0,0 +1,151 @@
# Линкер-скрипты: архитектурные детали
## Назначение
Линкер-скрипты управляют расположением секций ELF-образа ядра.
Для каждой архитектуры — свой скрипт, но все они следуют одной схеме.
## Общая структура
```
OUTPUT_FORMAT(...) ← формат ELF (зависит от архитектуры)
ENTRY(kmain) ← точка входа
PHDRS ← сегменты (program headers)
{
text PT_LOAD;
rodata PT_LOAD;
data PT_LOAD;
}
SECTIONS ← расположение секций
{
. = 0xffffffff80000000; ← база higher half
.text : { *(.text .text.*) } :text
. = ALIGN(MAXPAGESIZE);
.rodata : { *(.rodata .rodata.*) } :rodata
. = ALIGN(MAXPAGESIZE);
.data : {
*(.data .data.*)
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
} :data
.bss : { *(.bss .bss.*) *(COMMON) } :data
/DISCARD/ : { *(.eh_frame*) *(.note .note.*) }
}
```
## Детали
### OUTPUT_FORMAT
| Архитектура | Формат |
|-------------|--------|
| x86_64 | `elf64-x86-64` |
| aarch64 | `elf64-littleaarch64` |
| riscv64 | `elf64-littleriscv` |
| loongarch64 | `elf64-loongarch` |
### Базовый адрес: 0xFFFFFFFF80000000
Ядро размещается в **higher half** — верхней 2 GiB виртуального
адресного пространства. Это стандартная практика для x86-64:
```
0x0000_0000_0000_00000 ─── user space (не используется ядром)
0xFFFF_8000_0000_00000 ─── kernel space (higher half)
0xFFFF_FFFF_FFFF_FFFF ─── конец
```
Любой адрес в области 0xFFFF800000000000 — 0xFFFFFFFFFFFFFFFF корректен;
0xFFFFFFFF80000000 выбран как начало typical higher half региона.
### PHDRS: PT_LOAD сегменты
Bootloader загружает только PT_LOAD сегменты. Их три:
1. **text**: код + inline-константы.
2. **rodata**: неизменяемые данные (строки, таблицы).
3. **data**: изменяемые данные + BSS.
### Section alignment
```ld
. = ALIGN(CONSTANT(MAXPAGESIZE));
```
MAXPAGESIZE = 0x1000 (4 KiB). Каждая секция начинается с новой страницы,
что даёт bootloader'у правильные MMU permissionы:
- text = read + execute (no write)
- rodata = read (no write, no execute)
- data = read + write (no execute)
### Limine Requests в .data
```ld
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
```
- `KEEP` — запрещает линкеру выбрасывать эти секции (dead code elimination).
- `.requests_start_marker` и `.requests_end_marker` — маркеры границ.
- Bootloader сканирует память между ними, чтобы найти requests.
### BSS
```ld
.bss : {
*(.bss .bss.*)
*(COMMON)
} :data
```
- BSS — неинициализированные глобальные переменные.
- Занимает место в виртуальной памяти, но не в ELF-файле.
- Bootloader обнуляет BSS перед передачей управления.
### DISCARD
```ld
/DISCARD/ : {
*(.eh_frame*)
*(.note .note.*)
}
```
- `.eh_frame*` — исключительные фреймы C++/Rust unwinding.
- `.note.*` — ELF notes.
- Не нужны bare-metal ядру, могут вызвать проблемы.
## Архитектурные различия
### RISC-V
```ld
.data : {
*(.data .data.*)
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
*(.sdata .sdata.*) ← RISC-V: small data
} :data
.bss : {
*(.sbss .sbss.*) ← RISC-V: small BSS
*(.bss .bss.*)
*(COMMON)
} :data
```
RISC-V имеет `.sdata`/`.sbss` секции для small data (GP-relative addressing).
### AArch64 и LoongArch64
Идентичны x86_64, за исключением OUTPUT_FORMAT.