-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlinker.ld
More file actions
130 lines (114 loc) · 4.7 KB
/
Copy pathlinker.ld
File metadata and controls
130 lines (114 loc) · 4.7 KB
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
ENTRY(_boot)
/* Kernel virtual address base - upper half of address space */
KERNEL_VIRT_BASE = 0xFFFF000040000000;
/* Physical load address - where QEMU loads the kernel.
* When using flat binary with ARM64 Image header, QEMU loads at
* RAM_BASE + text_offset (when text_offset >= 4 KB QEMU uses it as-is;
* when text_offset < 4 KB QEMU adds 2 MB instead).
*
* text_offset = 1 MB (0x100000) → QEMU loads at RAM_BASE + 1 MB = 0x40100000.
*
* DTB placement: ALIGN_UP(kernel_load + image_size, 2MB).
* With kernel at 0x40100000 and image_size ≈ 0xCB000:
* ALIGN_UP(0x401CB000, 2MB) = 0x40200000
* So DTB goes to [0x40200000, 0x40300000) — fits in 4 MB with 1 MB spare.
*
* Pre-kernel region [0x40000000, 0x40100000) (1 MB) is free space reclaimed
* to the PMM pool after early boot.
*/
KERNEL_PHYS_BASE = 0x40100000;
/* Offset to convert between physical and virtual */
KERNEL_OFFSET = KERNEL_VIRT_BASE - KERNEL_PHYS_BASE;
SECTIONS
{
/*
* All code starts at physical address.
* Boot code runs with MMU off, rest runs with MMU on.
* We use one contiguous layout at physical addresses,
* and the kernel accesses everything via virtual addresses
* once MMU is enabled.
*/
. = KERNEL_PHYS_BASE;
/* Boot code - runs before MMU is enabled */
.text.boot : {
KEEP(*(.text._boot))
KEEP(*(.text.boot))
}
/* Boot data - also at physical addresses for pre-MMU access */
.data.boot : {
*(.data.boot)
}
/* Main kernel code */
_text_start = .;
.text : {
*(.text .text.*)
}
/* Exception vector table - must be 2KB aligned */
.text.exceptions : ALIGN(0x800) {
*(.text.exceptions)
}
_text_end = .;
/* Read-only data - page align for separate protection */
. = ALIGN(0x1000);
_rodata_start = .;
.rodata : {
*(.rodata .rodata.*)
}
_rodata_end = .;
/* Writable data - page align for separate protection */
. = ALIGN(0x1000);
_data_start = .;
.data : {
*(.data .data.*)
}
.bss (NOLOAD) : {
__bss_start = .;
/* Capture all BSS sections EXCEPT .bss.boot */
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_data_end = .;
/* Boot BSS - contains boot page tables */
/* Note: .bss.boot will be merged into .bss above due to .bss.* pattern */
/* The boot_page_tables symbol location doesn't matter as long as it's */
/* within the kernel's BSS and before _kernel_phys_end */
/* Record where kernel ends (physical) */
_kernel_phys_end = .;
/* Boot-stack reservation, derived from the *actual* linked image size so it
* auto-tracks the binary — there is no hand-tuned per-profile IMAGE_SIZE
* constant anymore. The boot stack is placed immediately above the kernel
* image (page-aligned, with a 2-page guard gap):
* STACK_BOTTOM = first page above the image + 2-page guard
* STACK_TOP = initial SP (boot.rs asm loads it); BOOT_STACK_SIZE above
* STACK_BOTTOM
* IMAGE_RESERVE = bytes from the load address to STACK_BOTTOM, for the
* ARM64 Image header (QEMU DTB placement)
* boot.rs (asm SP + Image header), src/main.rs (overlap guard + heap reserve +
* ExecConfig boot-stack bounds) and src/exceptions.rs (boot-thread exception
* stack) all read these as extern absolute symbols — one source of truth.
*
* BOOT_STACK_SIZE is injected by build.rs via --defsym (always passed, no
* PROVIDE — a PROVIDE default would silently override the defsym under LLD,
* the bug that once made the STACK_BOTTOM defsym a no-op). 1 MB for
* release/size (their boot test suite runs deep on thread 0); trimmed for the
* extreme target, where thread 0's measured high-water is ~10 KB. */
STACK_BOTTOM = ALIGN(_kernel_phys_end, 0x1000) + 0x2000;
STACK_TOP = STACK_BOTTOM + BOOT_STACK_SIZE;
IMAGE_RESERVE = STACK_BOTTOM - KERNEL_PHYS_BASE;
/DISCARD/ : {
*(.eh_frame)
}
}
/*
* Boot stack layout.
* STACK_BOTTOM / STACK_TOP / IMAGE_RESERVE are derived from _kernel_phys_end in
* the SECTIONS block above, so the boot-stack reservation always sits above the
* kernel image by construction and auto-tracks the binary on every build. The
* old ASSERT(_kernel_phys_end < STACK_BOTTOM) and the per-profile IMAGE_SIZE /
* --defsym=STACK_BOTTOM machinery (build.rs + boot.rs constants) are gone — there
* is nothing left to keep in lockstep. The check below can no longer fail; it is
* kept only as a self-documenting invariant.
*/
ASSERT(_kernel_phys_end < STACK_BOTTOM,
"FATAL: boot-stack reservation underflowed the kernel image (linker.ld bug)")