Page 1 of 1

page fault caused by mov instruction

Posted: Wed Jun 24, 2020 1:31 pm
by antoni
I don't even enabled paging, but I get "page fault" on the "mov" instruction.

Here short description of the error:

Code: Select all

page fault (exception 14)
error code: 0
stack frame:
        rip: 1205470
        cs: 8
        eflags: 518
cr2: 134092147
Instruction that caused fault is "mov":

Code: Select all

(gdb) x/10i 1205470
   0x1264de <find_facp+14>:	mov    0x4(%rdi),%eax
   0x1264e1 <find_facp+17>:	sub    $0x24,%rax
   0x1264e5 <find_facp+21>:	shr    $0x2,%rax
   0x1264e9 <find_facp+25>:	test   %eax,%eax
   0x1264eb <find_facp+27>:	jle    0x126550 <find_facp+128>
   0x1264ed <find_facp+29>:	sub    $0x1,%eax
   0x1264f0 <find_facp+32>:	mov    %rdi,%r15
   0x1264f3 <find_facp+35>:	xor    %ebx,%ebx
   0x1264f5 <find_facp+37>:	movabs $0x126600,%r13
   0x1264ff <find_facp+47>:	lea    0x4(,%rax,4),%r14
Why am I getting this error?

Re: page fault caused by mov instruction

Posted: Wed Jun 24, 2020 2:01 pm
by iansjack
If you haven't enabled paging then you are not getting a page fault.

As you have told us nothing about your code, or environment, other than something that is patently false it is difficult to say much more.

Edit: I note from your previous posts, and the minimal code you show here, that you are using long mode. Paging is a requisite for this. I'm not sure what happens if you use 64-bit instructions without enabling paging. Before anything else you need to set up a page table and enable paging.

Re: page fault caused by mov instruction

Posted: Wed Jun 24, 2020 9:12 pm
by nullplan
iansjack wrote:Edit: I note from your previous posts, and the minimal code you show here, that you are using long mode. Paging is a requisite for this. I'm not sure what happens if you use 64-bit instructions without enabling paging.
Nothing. It is impossible to be in long mode without paging enabled. Indeed, enabling the PG bit (while EFER.LME=1 and CR4.PAE=1 and CR3 is valid) is what makes the CPU go into long mode. However, when coming from UEFI, you will be in an identity-mapped environment. But that might be fragmented; not everything will be mapped.

@OP: Why did you show us the instructions from a different place than was reported by your exception handler? And if that is indeed the faulting instruction, your RDI is misaligned, since it is a 4-byte access, but CR2 is not divisible by 4. In any case, if you are using UEFI, allocate what memory you need for your own page tables and switch to them after ExitBootServices(). And if you just identity map all physical memory for the time being, that is good enough. Gigabyte pages are available.

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 1:13 am
by antoni
@iansjack

Probably I use paging, but only to enter long mode. I did it with some "minimal example" guide. I thought that paging was enabled in it in such a way that CPU would be happy, and in practice I'll never use it. Is it possible?

Code: Select all

 Why did you show us the instructions from a different place than was reported by your exception handler? 
After copying this, I changed something in the code. However, instruction is correct.

Code: Select all

However, when coming from UEFI
I don't have UEFI.

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 1:49 am
by iansjack
So you are using paging (as you must).

The address shown in %cr2 is way away from anything you would expect, so I suspect the problem lies in the value of %rdi. But that's just a guess - it's very difficult to say anything sensible without seeing your code. Why not provide a link to an on-line repository?
I did it with some "minimal example" guide.
It certainly looks that way. It would be beter to do a little reading so that you understand what you are doing rather than just blindly following some example you have found.

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 2:16 am
by antoni
Code archive: https://ufile.io/b5wxilgk

Page fault exception occurs in find_facp function from acpi.c file. This function is called in such a way in kernel.c file:

Code: Select all

vga_puti(find_facp(find_rsdt(find_rsdp())), 10);
Long mode is setted up in init.asm file.

I have make.sh script for building ISO image. You can run my kernel in such a way:

Code: Select all

qemu-system-x86_64 -hda kernel.iso
Or you can debug it with GDB in such a way:

Code: Select all

qemu-system-x86_64 -hda kernel.iso -s -S
and from another terminal execute:

Code: Select all

gdb -ex 'file kernel.bin' -ex 'set arch i386:x86-64:intel' -ex 'target remote localhost:1234'

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 7:51 am
by iansjack
find_facp() is called with parameter rootsdt=0x7fe157c.

There is no page mapping for the address 0x7fe157c.

Therefore, as soon as you access rootsdt you get a page fault.

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 8:20 am
by bzt
antoni wrote:Probably I use paging, but only to enter long mode. I did it with some "minimal example" guide. I thought that paging was enabled in it in such a way that CPU would be happy, and in practice I'll never use it. Is it possible?
If you have to ask, then this is the problem :-)

Listen to @iansjack, you should understand what the loader does, and how it sets up the environment for your kernel. You might need to tweak that according to your kernel's needs.

Take a look at my image receiver. It reads the kernel over serial line (that part you won't need), and if what received is an ELF64 executable, then it sets up long mode with identity mapping the first 1G RAM (the ACPI tables should be in it, but you can easily map 4G to be sure).

Cheers,
bzt

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 9:33 am
by antoni
I don't understand this part of your code:

Code: Select all

@@:         stosd
            add         edi, 4
            add         eax, 2*1024*1024
            dec         ecx
            jnz         @b

You are increasing edi by 4 but entries in long mode are 8 bytes long...

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 9:37 am
by bzt
antoni wrote:I don't understand this part of your code:

Code: Select all

@@:         stosd
            add         edi, 4
            add         eax, 2*1024*1024
            dec         ecx
            jnz         @b

You are increasing edi by 4 but entries in long mode are 8 bytes long...
Yes. The paging table is constructed in protmode, where you have only 32 bits, and we don't map over 4G (all addresses fit into 32 bits). So "stosd" puts the first 4 bytes with the address and flags, "add" simply skips another 4 bytes leaving that part as zero, that's 8 bytes in total for each entry.

Cheers,
bzt

Re: page fault caused by mov instruction

Posted: Thu Jun 25, 2020 2:28 pm
by antoni
It looks like I successfully addressed first gigabyte of memory and now... I get general protection fault in this same function also on mov instruction...

Code: Select all

general protection fault (exception 13)
error code: 0
rip: 1205549
cs: 8
eflags: 582

(gdb) x/10i 1205549
   0x12652d <find_facp+93>:	mov    (%rax,%rbx,1),%r12d
   0x126531 <find_facp+97>:	mov    %r12,%rdi
   0x126534 <find_facp+100>:	callq  *%r13
   0x126537 <find_facp+103>:	test   %eax,%eax
   0x126539 <find_facp+105>:	jne    0x126518 <find_facp+72>
   0x12653b <find_facp+107>:	add    $0x8,%rsp
   0x12653f <find_facp+111>:	mov    %r12,%rax
   0x126542 <find_facp+114>:	pop    %rbx
   0x126543 <find_facp+115>:	pop    %rbp
   0x126544 <find_facp+116>:	pop    %r12