Files
ai-forth-experiment/kernel_entry.S
T
haxala1r 1d16c23fc5 fix: correct multiboot2 framebuffer tag layout
Co-authored-by: aider (openrouter/anthropic/claude-opus-4.7) <aider@aider.chat>
2026-05-05 22:27:02 +03:00

185 lines
3.7 KiB
ArmAsm

# Multiboot2 header and x86_64 long-mode bootstrap
.section .multiboot2, "a"
.align 8
multiboot_header:
.long 0xe85250d6
.long 0
.long multiboot_header_end - multiboot_header
.long -(0xe85250d6 + 0 + (multiboot_header_end - multiboot_header))
/* Framebuffer tag: type=5, size=20, width=height=0 (any), depth=32.
* Layout per multiboot2 spec:
* u16 type, u16 flags, u32 size, u32 width, u32 height, u32 depth
* Padded to 8-byte alignment. */
.align 8
.word 5
.word 0
.long 20
.long 0
.long 0
.long 32
.long 0 /* padding to 8-byte alignment */
.align 8
.word 0
.word 0
.long 8
multiboot_header_end:
.section .bss, "aw", @nobits
.align 4096
pml4:
.space 4096
pdpt:
.space 4096
pd:
.space 4096 * 4
.align 16
stack_bottom:
.space 16384
stack_top:
.align 8
mboot_info_ptr:
.space 8
.section .text
.code32
.global _start
.type _start, @function
_start:
movl $stack_top, %esp
movl %ebx, mboot_info_ptr
cld
movl $__bss_start, %edi
movl $__bss_end, %ecx
subl %edi, %ecx
xorl %eax, %eax
rep stosb
movl $pdpt, %eax
orl $0x03, %eax
movl %eax, pml4
/* Populate 4 PDPT entries, each pointing to one of 4 PDs.
* This identity-maps the first 4 GiB using 2 MiB pages,
* which covers typical framebuffer/MMIO regions. */
movl $pd, %eax
orl $0x03, %eax
movl %eax, pdpt + 0
addl $4096, %eax
movl %eax, pdpt + 8
addl $4096, %eax
movl %eax, pdpt + 16
addl $4096, %eax
movl %eax, pdpt + 24
movl $0x00000083, %eax
movl $pd, %edi
movl $2048, %ecx
1:
movl %eax, (%edi)
addl $0x200000, %eax
addl $8, %edi
loop 1b
movl $pml4, %eax
movl %eax, %cr3
movl %cr4, %eax
orl $0x20, %eax
movl %eax, %cr4
movl $0xC0000080, %ecx
rdmsr
orl $0x100, %eax
wrmsr
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0
lgdt gdt64_pointer
ljmp $0x08, $long_mode_start
.code64
long_mode_start:
/* Load data segment registers with the data descriptor (0x10).
* In long mode most of these are ignored for access checks, but
* %ss must be a valid (or null) selector so that iretq from an
* interrupt can safely reload it. */
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
movabsq $stack_top, %rax
movq %rax, %rsp
/* Ensure 16-byte alignment for the System V AMD64 ABI. */
andq $-16, %rsp
movq mboot_info_ptr, %rdi
call kernel_main
cli
1:
hlt
jmp 1b
.code64
.global isr_keyboard
.align 16
isr_keyboard:
/* Save all caller-saved registers used by the SysV AMD64 ABI. */
pushq %rax
pushq %rcx
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
/* On interrupt entry the CPU pushed 5 qwords (40 bytes), and we
* pushed 9 more (72 bytes) = 112 bytes total. That leaves %rsp
* misaligned by 8 relative to a 16-byte boundary after the
* upcoming `call`. Push one dummy qword to realign. */
subq $8, %rsp
cld
call keyboard_handler
addq $8, %rsp
popq %r11
popq %r10
popq %r9
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rcx
popq %rax
iretq
.section .note.Xen, "a", @note
.align 4
.long 4
.long 4
.long 18
.asciz "Xen"
.align 4
.long _start
.section .rodata
.align 8
gdt64:
.quad 0x0000000000000000 /* 0x00: null descriptor */
.quad 0x00209A0000000000 /* 0x08: 64-bit code, DPL=0 */
.quad 0x0000920000000000 /* 0x10: data, writable, present */
gdt64_end:
gdt64_pointer:
.word gdt64_end - gdt64 - 1
.quad gdt64