Alignment problem in bootloader? [SOLVED](memory corruption)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
orbitaldecay
Posts: 13
Joined: Fri Nov 25, 2016 8:00 pm

Alignment problem in bootloader? [SOLVED](memory corruption)

Post by orbitaldecay »

I am working on a bootloader. In my bootloader I switch to long mode. On the long jump which loads the CS register, I get a triple fault in QEMU. Here is the code:

Code: Select all

	org 0x7c00
	bits 16

%define IDT_ADDR 0xF000
%define KERNEL_ADDR 0x10000
%define STACK_ADDR 0x40000
%define BLOCK_COUNT 127

	; Canonicalize IP
	jmp 0x0000:start
start:
	cli
	cld

	; Setup
        xor ax, ax
        mov ds, ax
        mov es, ax

        mov bx, 0x1000
        mov ss, bx
        mov sp, ax
	push 0xb800
	pop gs

        ; Read 127 sectors (64k) from begining of disk to memory
load:	mov word [dap + 2], BLOCK_COUNT
        mov ah, 42h
        mov si, dap
        int 0x13
        jc load

	; Turn on A20 gate (fast A20)
a20:	in al, 0x92
	or al, 2
	out 0x92, al

	; Set up long mode paging

	mov edi, 0x1000
	mov cr3, edi
	xor eax, eax
	mov ecx, 0x6000
	rep stosd

        ; 6 MB identity mapped

        mov word [0x1000], 0x2003
        mov word [0x2000], 0x3003

        mov word [0x3000], 0x4003
        mov word [0x3008], 0x5003
        mov word [0x3010], 0x6003

        mov ebx, 3
        mov ecx, 512 * 3
        mov edi, 0x4000
page:   mov dword [edi], ebx    ; [0x4000] = 0x0003, [0x4008] = 0x1003, ..., [0>
        add ebx, 0x1000
        add edi, 8
        loop page

	; Enable PAE
pae:	mov eax, cr4
	or eax, 1 << 5
	mov cr4, eax

        ; Load gdt
	lgdt [gdtr]

	; Switch to long mode
	mov ecx, 0xc0000080	; LM-bit
	rdmsr
	or eax, 1 << 8
	wrmsr
	mov eax, cr0		; Enable paging and protected mode
	or eax, 1 << 31 | 1 << 0
	mov cr0, eax
	jmp CODE_SEG:lmode

	bits 64
lmode:
However, if I add a nop immediately after

Code: Select all

start:
Then the code works fine in QEMU! My GDT and DAP are 32bit aligned. Any suggestions?
Last edited by orbitaldecay on Thu Jun 13, 2024 6:48 pm, edited 1 time in total.
orbitaldecay
Posts: 13
Joined: Fri Nov 25, 2016 8:00 pm

Re: Alignment problem in bootloader?

Post by orbitaldecay »

I think I found the issue. The following instructions must be prefixed by align 2 (they need to be 16bit aligned).

Code: Select all

        ; 6 MB identity mapped
        mov word [0x1000], 0x2003
        mov word [0x2000], 0x3003

        mov word [0x3000], 0x4003
        mov word [0x3008], 0x5003
        mov word [0x3010], 0x6003
I'm not entirely sure why, but the intel manual suggests it in 8.2.3.1 https://www.intel.com/content/dam/www/p ... manual.pdf "Instructions that read or write a word (2 bytes) whose address is aligned on a 2 byte boundary." will be treated as atomic (for the immediate value to be two byte aligned we simply need to align the instructions on a 2 byte value). Any other insights on this issue would still be appreciated.
orbitaldecay
Posts: 13
Joined: Fri Nov 25, 2016 8:00 pm

Re: Alignment problem in bootloader?

Post by orbitaldecay »

Another stupid bug. How did this work at all?

Code: Select all

   ; Set up long mode paging
   mov edi, 0x1000
   mov cr3, edi
   xor eax, eax
   mov ecx, 0x6000
   rep stosd
Should be

Code: Select all

   ; Set up long mode paging
   mov edi, 0x1000
   mov cr3, edi
   xor eax, eax
   mov ecx, 0x6000 / 4
   rep stosd
I was overwriting my bootloader!
Post Reply