ajhahn.de
← FlashOS
plain text 115 lines
/*
 * Kernel link script for QEMU's `-M virt` (AArch64).
 * Mirrors src/board/rpi4b/linker.ld; the only structural change
 * is the load base. PID 1 is ELF-loaded from the embedded initramfs
 * — the `user_init.o` blob and its
 * `user_start` / `user_end` wrapper are retired, same as on Pi.
 */

SECTIONS
{
    /DISCARD/ : { *(.eh_frame) *(.eh_frame_hdr) *(.note.*) *(.comment) }

    /* QEMU's `-M virt -kernel` (and a future UEFI/GRUB chain)
     * follow the Linux arm64 boot protocol: kernel entry at
     * 0x40080000, the standard load offset within the virt RAM
     * window starting at 0x40000000. Linking at the same base
     * means linker-resolved global pointers point at the bytes
     * the loader placed — no relocator needed at boot. */
    . = 0x40080000;
    _image_start = .;

    /* Linux arm64 boot header (64 bytes) — placed first so UEFI/GRUB
     * can identify the image. The branch at offset 0 jumps forward
     * to `_start_real` in `.text.boot`. */
    .text.boot.header : { KEEP(*(.text.boot.header)) }

    .text.boot : { *(.text.boot) *(.text.boot.late) *(.text.boot.literals) }
    .text : {
        *(.text)
        *(.text.*)
    }
    .rodata : {
        *(.rodata)
        *(.rodata.*)
    }
    .data : {
        *(.data)
        *(.data.*)
    }

    . = ALIGN(0x8);
    __start_patchable_functions = .;
    .patchable_function_entries : {
        KEEP(*(__patchable_function_entries))
    }
    __stop_patchable_functions = .;

    . = ALIGN(0x8);
    ksyms = .;
    symbols : {
        KEEP(*(_symbols))
    }

    . = ALIGN(0x8);
    bss_begin = .;
    .bss : {
        *(.bss)
        *(.bss.*)
        *(COMMON)
    }
    bss_end = .;

    /* Embedded initramfs — mirror of src/board/rpi4b/linker.ld. See
     * that file's comment for the symbol-area convergence rationale. */
    . = ALIGN(0x4);
    .initramfs : {
        KEEP(*(.initramfs))
    }

    . = ALIGN(0x1000);
    id_pg_dir = .;
    .data.id_pg_dir : { . += (3 * (1 << 12)); }
    high_pg_dir = .;
    .data.high_pg_dir : { . += (4 * (1 << 12)); }

    . = ALIGN(0x1000);
    _end = .;

    /* Linker-resolved image_size constant for the arm64 boot header.
     * `.quad _end - _image_start` in image_header.S would force GAS
     * to emit a subtraction expression on two extern symbols, which
     * GAS rejects; assigning here turns it into a single absolute
     * symbol the linker resolves. Same trick Linux uses
     * (`_kernel_size_le` in arch/arm64/kernel/vmlinux.lds.S). */
    _image_size = _end - _image_start;

    /* virt-only memory-backed SD scratch (src/board/virt/emmc2.zig's
     * 64 MiB `scratch`). NOLOAD, and placed LAST — after `_end` and
     * after `_image_size` is computed — so it shifts nothing the boot
     * path depends on: not bss_begin/bss_end (boot.S clears bss via
     * `adr x1, bss_end`, ±1 MiB PC-relative; a 64 MiB `.bss` member
     * overflows that reloc), not id_pg_dir/high_pg_dir (must stay in
     * virt's 16 MiB identity window), not `_image_size` (QEMU's DTB
     * placement). emmc2.init() @memsets the buffer itself, so it does
     * not need the boot.S bss memzero. At runtime the kernel runs at
     * the LINEAR_MAP_BASE alias whose RAM map covers 0x40000000..
     * 0x80000000, so the buffer is reachable. No rpi4b counterpart —
     * rpi4b's EMMC2 driver is real MMIO with no backing array. */
    . = ALIGN(0x1000);
    .sdscratch (NOLOAD) : {
        KEEP(*(.sdscratch))
    }

    /* End-of-reserved-PA marker for the get_free_page pool. virt loads
     * the kernel at PA 0x40080000, inside the pool's MALLOC_START
     * (0x40000000) window, so mem_map_reserve_below(_kernel_pa_end)
     * must mark every page up to and including sdscratch as allocated
     * — otherwise get_free_page hands out PAs that overlap the kernel
     * image and memzero corrupts kernel code (notably memzero itself
     * around PA 0x40081000), leading to a silent stall. Pi has the
     * mirror symbol defined as a no-op (kernel below the pool). */
    . = ALIGN(0x1000);
    _kernel_pa_end = .;
}