QEMU page faults upon mov edx, imm32
Posted: Sat Dec 07, 2024 7:55 am
I'm working on adding paging to my kernel which has so far been working well with physical addresses. I'm basing it off off the x86 Higher Half tutorial, but I'm writing the assembly code myself, as I want the simpler scheme of just mapping the first 8 MiB to the higher quarter, 0x00xxxxxx to 0xC0xxxxxx. The linker script puts the main .text section, which contains ISRs and C code, at virtual offset +0xC0000000, and we put the paging bootstrap code in a separate .multiboot.text section, as in the tutorial.
My code reads as follows:
I've figured out how to combine the QEMU monitor - internal debugger - with gdb, which is quite useful. QEMU doesn't complain when I boot this as it did when I hadn't gotten the linker script quite right ("PVH ELF note" etc). A page fault occurs at address 0x201047, which is the instruction.
The monitor's logs aren't much more than those obtained by -d int. Both using gdb to inspect the memory at CR3 and using the monitor's info mem and info tlb commands shows that the desired mapping is present, read-write. So why on earth does moving an immediate into EDX page fault? Screenshots attached.
My code reads as follows:
Code: Select all
.section .bss
.global stack_top
.align 16
stack_bottom:
.skip 16384
stack_top:
.align 4096
boot_pd:
.skip 4096
boot_pt:
.skip 4096
.section .multiboot.text, "a"
.global _start
.type _start, @function
_start:
/* Place the page table in the page directory; it should be the 768'th page table out of 1024 */
movl $(boot_pt - 0xC0000000), %esi
movl $(boot_pd - 0xC0000000), %edi
orl $0x3, %esi
movl %esi, 0xC00(%edi)
/* Map 0x00XXXyyy to 0xC0XXXyyy for all X from 0 to 0x3FF (first 4 MiB of physmem) */
movl $0, %ecx
movl %esi, %edi
andl $0xFFFFFFFC, %edi
1:
cmpl $0x3FF, %ecx
jg 2f
/* The entry in the page table is boot_pt - 0xC0000000 + 4 * %ecx, our page is 4096 * %ecx */
movl %ecx, %esi
shll $12, %esi
orl $0x3, %esi
movl %esi, (%edi, %ecx, 4)
incl %ecx
jmp 1b
2:
/* Tell them where our page directory is and enable CR0's PG bit */
movl $(boot_pd - 0xC0000000), %edi
movl %edi, %cr3
movl %cr0, %edx
orl $0x80000000, %edx
movl %edx, %cr0
movl $kernel_begin, %edx
jmp *%edx
.size _start, . - _start
.section .text
kernel_begin:
[... set up stack and enter C kernel ...]
Code: Select all
movl $kernel_begin, %edx
The monitor's logs aren't much more than those obtained by -d int. Both using gdb to inspect the memory at CR3 and using the monitor's info mem and info tlb commands shows that the desired mapping is present, read-write. So why on earth does moving an immediate into EDX page fault? Screenshots attached.