Paging enable causing triple fault

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
daniil1909
Posts: 6
Joined: Wed Sep 13, 2023 10:52 pm

Paging enable causing triple fault

Post by daniil1909 »

When i enabling paging in my os i getting triple fault at 101aad

paging.c:

Code: Select all

/** @file paging.c
 *  Copyright (c) 2024 FigaSystems
 *  Memory Paging
 *  @author Daniil Dunaef
 *  @date 14-Aug-2024
 *  @bug No current bugs found
*/



#include "mm/paging.h"
#include "FOSdef.h"

extern void PGInstallPageDirectory();
extern void PGEnablePaging();

unsigned int PageDirectory[1024] __attribute__((aligned(4096)));
unsigned int PageTable[1024] __attribute((aligned(4096)));

FOSKERNELAPI
VOID
PGInitializePageDirectory(
    CHAR Present,
    CHAR ReadWrite,
    CHAR UserSuperior,
    CHAR WriteThrough,
    CHAR CacheDisable,
    CHAR Accessed,
    CHAR PageSize
)
{
    for (int i = 0; i < 1024; i++)
        PageDirectory[i] = Present | ReadWrite << 1 | UserSuperior << 2 | WriteThrough << 3 | CacheDisable << 4 | Accessed << 5 | PageSize << 6;
}

FOSKERNELAPI
VOID
PGInitializePageTable(
    CHAR Present,
    CHAR ReadWrite,
    CHAR UserSuperior,
    CHAR WriteThrough,
    CHAR CacheDisable,
    CHAR Accessed,
    CHAR Dirty,
    CHAR PageAttributeTable,
    CHAR Global
)
{
    for (int i = 0; i < 1024; i++)
        PageTable[i] = (i * 0x1000) | Present | ReadWrite << 1 | UserSuperior << 2 | WriteThrough << 3 | CacheDisable << 4 | Accessed << 5 | Dirty << 6 | PageAttributeTable << 7 | Global << 8;

    PageDirectory[0] |= ((unsigned int)PageTable);
}

FOSKERNELAPI
VOID
PGSetPageTableEntry(
    INT PageTableIndex,
    INT Address,
    CHAR Present,
    CHAR ReadWrite,
    CHAR UserSuperior,
    CHAR WriteThrough,
    CHAR CacheDisable,
    CHAR Accessed,
    CHAR Dirty,
    CHAR PageAttributeTable,
    CHAR Global
)
{
     PageTable[PageTableIndex] = Address << 11 | Present | ReadWrite << 1 | UserSuperior << 2 | WriteThrough << 3 | CacheDisable << 4 | Accessed << 5 | Dirty << 6 | PageAttributeTable << 7 | Global << 8;
}

FOSKERNELAPI
VOID
PGInitializePaging(
    VOID
)
{
    PGInitializePageDirectory(0, 1, 0, 0, 0, 0, 0);
    PGInitializePageTable(1, 1, 0, 0, 0, 1, 0, 0, 0);

    PGInstallPageDirectory();
    PGEnablePaging();
}
paging.asm:

Code: Select all

; File: paging.asm
; Copyright (c) 2024 Figasystems
; Paging
; Author: Daniil Dunaef
; Date: 14-Aug-2024
; Bugs no Bugs

global PGInstallPageDirectory
global PGEnablePaging

extern PageDirectory

PGInstallPageDirectory:
    push ebp
    mov ebp, esp
    mov eax, [PageDirectory]
    mov cr3, eax
    mov ebp, esp
    pop ebp
    ret

PGEnablePaging:
    push ebp
    mov ebp, esp
    mov eax, cr0
    or eax, 0x80000000
    mov cr0, eax
    ret
Qemu:

Code: Select all

Servicing hardware INT=0x08
check_exception old: 0xffffffff new 0xe
     0: v=0e e=0000 i=0 cpl=0 IP=0008:00101aad pc=00101aad SP=0010:00106f08 CR2=00101aad
EAX=80000011 EBX=00010000 ECX=00000000 EDX=00108000       
ESI=00000000 EDI=00000000 EBP=00106f08 ESP=00106f08       
EIP=00101aad EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]      
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00116140 0000002f
IDT=     00116180 000007ff
CR0=80000011 CR2=00101aad CR3=00108002 CR4=00000000       
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000084 CCD=80000011 CCO=EFLAGS
EFER=0000000000000000
check_exception old: 0xe new 0xe
     1: v=08 e=0000 i=0 cpl=0 IP=0008:00101aad pc=00101aad SP=0010:00106f08 env->regs[R_EAX]=80000011
EAX=80000011 EBX=00010000 ECX=00000000 EDX=00108000
ESI=00000000 EDI=00000000 EBP=00106f08 ESP=00106f08       
EIP=00101aad EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]      
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00116140 0000002f
IDT=     00116180 000007ff
CR0=80000011 CR2=001161f0 CR3=00108002 CR4=00000000       
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000       
DR6=ffff0ff0 DR7=00000400
CCS=00000084 CCD=80000011 CCO=EFLAGS
EFER=0000000000000000
check_exception old: 0x8 new 0xe
Triple fault
nullplan
Member
Member
Posts: 1760
Joined: Wed Aug 30, 2017 8:24 am

Re: Paging enable causing triple fault

Post by nullplan »

So which tutorial did you copy this code from? Or was it ChatGPT? Because this is generally what I'd expect from badly written tutorials or AI code.

Your assembler routines all set up a stack frame, even though they don't need it, and PGEnablePaging() doesn't tear it down properly and jumps off into the bushes somewhere. And PGInstallPageDirectory() sets as CR3 the first word from the page directory, not the address of the page directory. Why don't you just pass the address as a parameter?
Carpe diem!
daniil1909
Posts: 6
Joined: Wed Sep 13, 2023 10:52 pm

Re: Paging enable causing triple fault

Post by daniil1909 »

nullplan wrote: Wed Aug 14, 2024 8:37 am So which tutorial did you copy this code from? Or was it ChatGPT? Because this is generally what I'd expect from badly written tutorials or AI code.

Your assembler routines all set up a stack frame, even though they don't need it, and PGEnablePaging() doesn't tear it down properly and jumps off into the bushes somewhere. And PGInstallPageDirectory() sets as CR3 the first word from the page directory, not the address of the page directory. Why don't you just pass the address as a parameter?
I wrote it myself, i am poor in assembly so i dont know how to set CR3 as address of page directory (as i know mov register, [value] means move address of value) aslo, i dont really know how to pass the address (i written some x86 assembly programs but never used c and assembly together)

I rewrote my code now its looks like this:

Code: Select all

; File: paging.asm
; Copyright (c) 2024 Figasystems
; Paging
; Author: Daniil Dunaef
; Date: 14-Aug-2024
; Bugs no Bugs

global PGInstallPageDirectory
global PGEnablePaging

PGInstallPageDirectory:
    mov eax, [ebp + 8]
    mov cr3, eax
    ret

PGEnablePaging:
    mov eax, cr0
    or eax, 0x80000000
    mov cr0, eax
    ret
still faults:

Code: Select all

Servicing hardware INT=0x08
check_exception old: 0xffffffff new 0xe
     0: v=0e e=0000 i=0 cpl=0 IP=0008:00101ab2 pc=00101ab2 SP=0010:00106f0c CR2=00101ab2
EAX=80000011 EBX=00010000 ECX=00000000 EDX=00108000       
ESI=00000000 EDI=00000000 EBP=00106f18 ESP=00106f0c       
EIP=00101ab2 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]      
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy      
GDT=     00116140 0000002f
IDT=     00116180 000007ff
CR0=80000011 CR2=00101ab2 CR3=00000000 CR4=00000000       
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000       
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=80000011 CCO=LOGICL
EFER=0000000000000000
check_exception old: 0xe new 0xe
     1: v=08 e=0000 i=0 cpl=0 IP=0008:00101ab2 pc=00101ab2 SP=0010:00106f0c env->regs[R_EAX]=80000011
EAX=80000011 EBX=00010000 ECX=00000000 EDX=00108000       
ESI=00000000 EDI=00000000 EBP=00106f18 ESP=00106f0c
EIP=00101ab2 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]      
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy      
GDT=     00116140 0000002f
IDT=     00116180 000007ff
CR0=80000011 CR2=001161f0 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000       
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=80000011 CCO=LOGICL
EFER=0000000000000000
check_exception old: 0x8 new 0xe
Triple fault
MichaelPetch
Member
Member
Posts: 762
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Paging enable causing triple fault

Post by MichaelPetch »

Your new code has:

Code: Select all

 PGInstallPageDirectory:
    mov eax, [ebp + 8]
    mov cr3, eax
    ret
The problem here is that EBP hasn't been set with anything useful to your function. You could put the `push ebp` `mov ebp,esp` back with a `pop ebp` at the end and use `mov eax, [ebp+8] but in this case it would just be easier to modify the function to be:

Code: Select all

PGInstallPageDirectory:
    mov eax, [esp + 4]
    mov cr3, eax
    ret
ESP+0 = return address and ESP+4 is first argument ESP+8 is second.
It may also be worth noting that

Code: Select all

PGInitializePageDirectory(0, 1, 0, 0, 0, 0, 0);
has the first argument a 0 which sets the PageDirectory entries not present. I believe you'll want to set at least the entries covering your kernel and its data to present otherwise it will page fault.
daniil1909
Posts: 6
Joined: Wed Sep 13, 2023 10:52 pm

Re: Paging enable causing triple fault

Post by daniil1909 »

MichaelPetch wrote: Wed Aug 14, 2024 9:12 pm Your new code has:

Code: Select all

 PGInstallPageDirectory:
    mov eax, [ebp + 8]
    mov cr3, eax
    ret
The problem here is that EBP hasn't been set with anything useful to your function. You could put the `push ebp` `mov ebp,esp` back with a `pop ebp` at the end and use `mov eax, [ebp+8] but in this case it would just be easier to modify the function to be:

Code: Select all

PGInstallPageDirectory:
    mov eax, [esp + 4]
    mov cr3, eax
    ret
ESP+0 = return address and ESP+4 is first argument ESP+8 is second.
It may also be worth noting that

Code: Select all

PGInitializePageDirectory(0, 1, 0, 0, 0, 0, 0);
has the first argument a 0 which sets the PageDirectory entries not present. I believe you'll want to set at least the entries covering your kernel and its data to present otherwise it will page fault.
still faults:

Code: Select all

Servicing hardware INT=0x08
check_exception old: 0xffffffff new 0xe
     0: v=0e e=0000 i=0 cpl=0 IP=0008:00101ab3 pc=00101ab3 SP=0010:00106f0c CR2=00101ab3
EAX=80000011 EBX=00010000 ECX=00000000 EDX=00108000       
ESI=00000000 EDI=00000000 EBP=00106f18 ESP=00106f0c       
EIP=00101ab3 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy      
GDT=     00116140 0000002f
IDT=     00116180 000007ff
CR0=80000011 CR2=00101ab3 CR3=00107000 CR4=00000000       
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000       
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=80000011 CCO=LOGICL
EFER=0000000000000000
check_exception old: 0xe new 0xe
     1: v=08 e=0000 i=0 cpl=0 IP=0008:00101ab3 pc=00101ab3 SP=0010:00106f0c env->regs[R_EAX]=80000011
EAX=80000011 EBX=00010000 ECX=00000000 EDX=00108000       
ESI=00000000 EDI=00000000 EBP=00106f18 ESP=00106f0c       
EIP=00101ab3 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]      
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]      
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy      
GDT=     00116140 0000002f
IDT=     00116180 000007ff
CR0=80000011 CR2=001161f0 CR3=00107000 CR4=00000000       
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=80000011 CCO=LOGICL
EFER=0000000000000000
check_exception old: 0x8 new 0xe
Triple fault
MichaelPetch
Member
Member
Posts: 762
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Paging enable causing triple fault

Post by MichaelPetch »

0: v=0e e=0000 i=0 cpl=0 IP=0008:00101ab3 pc=00101ab3 SP=0010:00106f0c CR2=00101ab3
v=0e (hex) is a pagefault. e=0000 (hex) means there was a non-present page in kernel mode when trying to read memory at 00101ab3 (CR2). See https://wiki.osdev.org/Exceptions#Error_code
nullplan
Member
Member
Posts: 1760
Joined: Wed Aug 30, 2017 8:24 am

Re: Paging enable causing triple fault

Post by nullplan »

Another issue I see off-hand is that you are shifting the address in PGInitializePageTable(). Page table entries are really just the address of the next level, with some flags ORed in. And again, you are not setting the first page directory entry to "present".
Carpe diem!
Post Reply