OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Oct 06, 2022 11:23 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Interrupts seem to invalidate stack
PostPosted: Sat Aug 13, 2022 5:12 am 
Offline

Joined: Sat Aug 13, 2022 4:57 am
Posts: 4
I have an issue where my interrupt code seems to be corrupting the stack, which in very specific cases causes a page fault.

This is such a case:
Code:

0xffffff8000011fce: mov    -0x8(%rbp),%rax
0xffffff8000011fd2: movb  $0x0,(%rax)

When the return address is the first instruction a page fault is thrown at the second instruction which complains that the address 0x0 is unmapped. These page faults are thrown whenever this pattern occurs in the interrupted code.
My assembly interrupt code:
Code:
mouse_asm:
    cli
    sub rsp, 8

    push rax
    push rbx
    push rcx
    push rdx
    push rsp
    push rbp
    push rsi
    push rdi
    push r8
    push r9
    push r10
    push r11
    push r12
    push r13
    push r14
    push r15

    mov ax, ds
    push rax

    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    call _ZN11MouseDriver15HandleInterruptE9int_frame

    pop rax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    pop r15
    pop r14
    pop r13
    pop r12
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdi
    pop rsi
    pop rbp
    pop rsp
    pop rdx
    pop rcx
    pop rbx
    pop rax

    add rsp, 8

    sti
    iretq

(I know not all these registers have to be stored I just did to make sure. Also, I normally use a common stub which is why the stack pointer is incremented by 8 in the beginning.)

And the called C++ code:
Code:
void MouseDriver::HandleInterrupt(int_frame frame){
    while(IO::In(0x64) & 0x1) IO::In(0x60);
    IO::Out(PIC1_COMMAND_PORT, 0x20);
    IO::Out(PIC2_COMMAND_PORT, 0x20);
    return;
}

The page faults also occurs for keyboard and PIT interrupts, I'm just using the mouse for convenience's sake. I can also post the disassembled interrupted code if necessary.

I have been stuck on this for a while now so it would be really awesome if this issue were finally resolved, thanks in advance.


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Sun Aug 14, 2022 7:38 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 4177
You're following a buggy tutorial and you've run into one of the bugs. When you pass a struct by value, the contents of the struct may be overwritten by the function. You need to pass a pointer (or perhaps a reference?) to the struct in order to preserve its contents.

Also, you shouldn't push/pop RSP.

Also, your handler shouldn't start with CLI. If you want interrupts disabled, use an interrupt gate.

Also, your handler shouldn't have STI before IRETQ. IRETQ will update RFLAGS.IF according to the value on the stack.

Also, you need CLD before you call any C++ functions inside an interrupt handler.

Also, you need to ensure your stack is correctly aligned before you call any C++ functions. (The CPU automatically aligns the stack before pushing the return address and return stack pointer, so you can align the stack by making sure you push the right number of values. It might already be correctly aligned - I haven't checked.)


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Mon Aug 15, 2022 3:40 am 
Offline

Joined: Sat Aug 13, 2022 4:57 am
Posts: 4
I'm not following specifically his tutorial, but bad code seems to be very widespread online if you can't use the struct itself as an argument.

I have changed the things you commented on however, and my assembly code now looks like this:
Quote:
mouse_asm:
cli
cld

PUSHALL

mov ax, ds
push rax

mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

mov rdi, rsp
mov r12, rsp
and rsp, -16

call _ZN11MouseDriver15HandleInterruptEP9int_frame

mov rsp, r12

pop rax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

POPALL

iretq

(PUSHALL and POPALL are macros that push and pop the registers, not including rsp)

I still get the same issue I got before however, even now that I'm passing a pointer to the struct. Maybe noteworthy: I used to have the same issue when using GCC's interrupt attribute. It's why I switched to assembly stubs in the first place, but that hasn't changed anything. Could that mean the error isn't in my assembly code?


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Mon Aug 15, 2022 4:06 am 
Offline
Member
Member
User avatar

Joined: Fri Jun 11, 2021 6:02 am
Posts: 79
Location: Belgium
hoiblij wrote:
Code:
    pop rax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax



I keep seeing this so I decided to take a look at the tutorial. AFAICT the tutorial only deals with protected (32-bit) mode, not long (64-bit) mode where setting the segment registers is useless.

The exceptions are SS and CS, which are saved and restored by the interrupt and iretq automatically anyways.

Please read the Features section on the X86-64 page.

Also, a minor nit but you don't need to save all registers if you don't modify them directly and follow the calling conventions.

(FWIW, I checked Linux' source and they don't save segment registers in long mode either.)

_________________
My OS is Norost B (website, Github, sourcehut)


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Mon Aug 15, 2022 10:10 am 
Offline
Member
Member

Joined: Sat Nov 21, 2009 5:11 pm
Posts: 797
Never copy code you found online, period. You have no way to know if the author knows what he's doing.

This anti-pattern is beyond stupid, and whenever encountered should be an indication to stop wasting your time and close the page:
Code:
push ds
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax ; just in case I feel like decorating my code with random FS prefixes
mov gs, ax ; or GS prefixes, for variety
; do stuff
pop eax
mov ds, ax
mov es, ax ; one segment should be enough for everyone
mov fs, ax ; I assume no one was using these for anything important
mov gs, ax ; God knows what these registers do anyway

This is what happens when code is copied and pasted on the internet indiscriminately. Completely ridiculous and pointless.


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Mon Aug 15, 2022 11:51 am 
Offline

Joined: Sat Aug 13, 2022 4:57 am
Posts: 4
I was aware that (re)storing the segment registers was likely useless, I just did to be sure. I have removed it from my code, but it is still not working as expected.


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Mon Aug 15, 2022 11:56 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 4177
I don't see anything else in your interrupt code that might corrupt the stack. Are you sure the problem is stack corruption and not red zone corruption?


Top
 Profile  
 
 Post subject: Re: Interrupts seem to invalidate stack
PostPosted: Mon Aug 15, 2022 4:59 pm 
Offline

Joined: Sat Aug 13, 2022 4:57 am
Posts: 4
Wow, I had never heard about the red zone at all before. Perhaps it was mentioned on the wiki but I simply missed it. I added the -mno-red-zone flag and the issue is gone now, what a stupid thing to miss. Thanks a ton for all the help tho!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 17 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group