Why does syscall is causing Page fault at address 0x0?

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
User avatar
gamingjam60
Member
Member
Posts: 52
Joined: Sat Aug 24, 2024 10:06 pm
Libera.chat IRC: gamingjam60
Location: India
GitHub: https://github.com/baponkar
Contact:

Why does syscall is causing Page fault at address 0x0?

Post by gamingjam60 »

My user Program is

Code: Select all

[BITS 64]
global _start

section .text
_start:
    ;syscall(SYSCALL_PRINT, (uint64_t)msg, 0)
    mov     rax, 1                  ; SYSCALL_PRINT = 1
    lea     rdi, [rel msg]          ; First argument: pointer to message
    xor     rsi, rsi                ; Second argument (not used)
    syscall                         ; Perform syscall

    ; syscall(SYSCALL_EXIT, 0, 0)
    mov     rax, 3                  ; SYSCALL_EXIT = 3
    xor     rdi, rdi                ; First argument: exit code 0
    xor     rsi, rsi                ; Second argument (unused)
    syscall                         ; Exit syscall

.hang:
    jmp     .hang                   ; If syscall fails, loop forever

section .data
msg: db "Hello from user via syscall!", 0
Store syscall_entry by

Code: Select all

write_msr(MSR_LSTAR, (uint64_t)&syscall_entry);
and

Code: Select all

syscall_entry:
    swapgs                    ; switch GS base with KernelGSBase

    mov [gs:0x10], rsp        ; Save old kernel RSP
    mov rsp, [gs:8]           ; Load per-core kernel stack
    sub rsp, 8*8              ; make room for pushes (align if needed)

    ; Don't touch RCX or R11! They are used by sysretq.
    push rcx 
    push r11 

    ; Save other registers
    push rdi
    push rsi
    push rdx
    push rax
    push r8
    push r9

    ; Arguments to syscall_handler(syscall_num, arg1)
    mov rsi, rdi         ; user argument → RSI
    mov rdi, rax         ; syscall number → RDI

    call syscall_handler

    ; Restore registers
    pop r9
    pop r8
    pop rax
    pop rdx
    pop rsi
    pop rdi

    pop r11 
    pop rcx 

    swapgs              ; switch GS base with KernelGSBase

    ; Return to user — RCX and R11 must still hold original values
    sysretq

You can see I have stored rcx but

Code: Select all

void syscall_handler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2) {

    switch(syscall_num) {
        case SYSCALL_PRINT:
            const char* str = (const char*)arg1;
            printf("%s\n", str);  
            break;

        case SYSCALL_READ:
            // Handle read syscall
            char* user_buf = (char*)arg1;
            uint64_t size = arg2;
            // Implement read logic here
            break;

        case SYSCALL_EXIT:
            printf("User requested shell exit.\n");
            break;

        default:
            printf("Unknown syscall: %d\n", (int) syscall_num);
    }
}
When I am using switch_to_user_mode(user_stack, user_entry);

Code: Select all

Hello from user via syscall!
Page fault! ( Page not present, User-mode, Instruction fetch, ) at address 0x0
Halting the system due to page fault.
successfully run first syscall_handler after jumping in address 0x0 but it should call next syscall which is mentioned in user_program. Why it is happening?
Octocontrabass
Member
Member
Posts: 5873
Joined: Mon Mar 25, 2013 7:01 pm

Re: Why does syscall is causing Page fault at address 0x0?

Post by Octocontrabass »

gamingjam60 wrote: Thu Jun 19, 2025 8:10 am

Code: Select all

    sysretq
Doesn't NASM warn you about this?
User avatar
gamingjam60
Member
Member
Posts: 52
Joined: Sat Aug 24, 2024 10:06 pm
Libera.chat IRC: gamingjam60
Location: India
GitHub: https://github.com/baponkar
Contact:

Re: Why does syscall is causing Page fault at address 0x0?

Post by gamingjam60 »

Octocontrabass wrote: Thu Jun 19, 2025 7:21 pm
gamingjam60 wrote: Thu Jun 19, 2025 8:10 am

Code: Select all

    sysretq
Doesn't NASM warn you about this?
No warning for sysretq.

I added following lines

Code: Select all

...
 mov r12, rcx                ; Save RCX to check it
 mov r13, rdi                ; Save RDI into r13
 mov rdi, r12                ; Move RCX value to first argument
 call print_hex              ; Or any function that prints uint64_t
 mov rdi, r13                ; restore rdi with original value
 ...
 
The output:

Code: Select all

Switching into usermode: user_entry_addr-0x401000, user_stack_addr-0x1000
0x401011Unknown syscall: 736
Page fault! ( Page not present, User-mode, Instruction fetch, ) at address 0x2EB
Halting the system due to page fault.
The above output is showing RCX=0x401011 what might seem to be right and also 2nd syscall run after 1st syscall but not third .

But without above lines the output becomes

Code: Select all

Switching into usermode: user_entry_addr-0x401000, user_stack_addr-0x1000
Hello from user via syscall!
Page fault! ( Page not present, User-mode, Instruction fetch, ) at address 0x0
Halting the system due to page fault.
The output is showing only 1st syscall is run and jump into 0x0.

What is happening in here?
User avatar
iansjack
Member
Member
Posts: 4811
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Why does syscall is causing Page fault at address 0x0?

Post by iansjack »

gamingjam60 wrote: Fri Jun 20, 2025 7:13 amNo warning for sysretq.
Does that mean you did get some warnings?

You won't get a warning specifying "sysretq" but you should get the warning

"warning: label alone on a line without a colon might be in error [-w+label-orphan]".

(Unless you have disabled warnings, and why would anyone do that?)
Post Reply