OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 2:37 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: INT instruction stack behavior in x86-64 (Bochs)
PostPosted: Thu Aug 03, 2017 5:38 am 
Offline
User avatar

Joined: Sat Sep 05, 2015 2:10 am
Posts: 11
Location: Italy
Hello everyone, I'm an italian student, and I'm rewriting for the fourth time (I still have a lot to learn about OS development), my simple OS. I'm trying to improve this version so much, so I decided to implement long mode, and maybe graphics for the first time, after a studying pause.
I'm still working on the bootloader, so my environment consists in NASM, bochs, other universal tools like an hex-editor, running in LinuxMint 18.2 'Sonya' on a HP P6 Pavilion (2011) machine. I successfully set up Long Mode, identity paging the first 4Mb of memory, and a basic environment, like keyboard's and RTC's IRQ handler(still developing to achieve HPET), but I found something strange when debugging my system call handler (INT 80h).
My syscall handler needs some quadword data to be pushed on the stack, just before the (r_flags if I remember right) data pushed by the INT instruction. Unlike common practice, I make the callee clean the stack, by moving the stack 8 byte upwards unless it moves the byte pointed by current ESP, then adding ESP,08h . This is done for every parameter needed by the called function. The only problem of this method is that it needs to know the number of byte pushed by the INT instruction, that's a known value and shouldn't be hard to find.
However, I found only partial data on INT instruction behavior in x86-64, so I tried to check it out by the following code(relying on Bochs magic breakpoint tool):
Code:
;IRQ's and NMI's are previously disabled, and current ESP location saved in memory
        MOV     RSP,1000h       ;Address totally free of useful data
        XCHG    BX,BX           ;First Breakpoint
        INT     81h             ;Calls int 81h handler written for this puorpose
        XCHG    BX,BX           ;Third Breakpoint 

And this is the code of the INT 81h handler:
Code:
;Performs just a breakpoint and returns
        XCHG    BX,BX           ;Second Breakpoint
        IRETQ

That's very simple, when setting ESP on every 16-byte aligned address, at the breakpoints I got always the same RSP values:

  1. 1000h
  2. 0FD8h
  3. 1000h

So seemed to be pushed 0x28 bytes. But then I repeated the experiment by pushing a QWORD value, before calling INT 81h, so setting RSP to 0x0FF8:
Code:
;IRQ's and NMI's are previously disabled, and current ESP location saved in memory
        MOV     RSP,1000h       ;Address totally free of useful data
        PUSH    RAX             ;Pushes RAX (that is equal to 0xAAAAAAAA_AAAAAAAA)on the stack
        XCHG    BX,BX           ;First Breakpoint
        INT     81h             ;Calls int 81h handler written for this puorpose
        XCHG    BX,BX           ;Third Breakpoint 

In this case, and in all cases with all 8-byte aligned RSP values before the INT call, the RSP values at the breakpoints are the following:

  1. 0FF8h
  2. 0FC8h (and not FD0 as expected)
  3. 0FF0h (8-bytes under the original value!!!)

I haven't noticed that yet, because every handler worked well, as Bochs seems to push the important values AFTER pushing the content of RBP or RCX (it seems to choose randomly between these).
This introduces a very dangerous misalignment in the stack, as a "useless" information is pushed and never popped.
Can anybody please explain why is this happening? Is a Bochs bug, or does long mode need to work with 16-byte aligned stack addresses, or anything else?

_________________
You learn more by a single triple fault than by reading the whole Intel specification...


Top
 Profile  
 
 Post subject: Re: INT instruction stack behavior in x86-64 (Bochs)
PostPosted: Fri Aug 04, 2017 2:35 am 
Offline
Member
Member

Joined: Fri Apr 04, 2008 6:43 am
Posts: 357
The interrupt invocation in 64-bit mode aligning stack to 16-bye boundary:

NTER-PRIVILEGE-LEVEL-INTERRUPT:
.....
IF (IA32_EFER.LMA = 0) (* Not IA-32e mode *)
THEN
IF instruction pointer from IDT gate is not within new code-segment limits
THEN #GP(EXT); FI; (* Error code contains NULL selector *)
ESP ← NewESP;
SS ← NewSS; (* Segment descriptor information also loaded *)
ELSE (* IA-32e mode *) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< read here
IF instruction pointer from IDT gate contains a non-canonical address
THEN #GP(EXT); FI; (* Error code contains NULL selector *)
RSP ← NewRSP & FFFFFFFFFFFFFFF0H; <===== align RSP
SS ← NewSS;
FI


Top
 Profile  
 
 Post subject: Re: INT instruction stack behavior in x86-64 (Bochs)
PostPosted: Fri Aug 04, 2017 10:21 am 
Offline
User avatar

Joined: Sat Sep 05, 2015 2:10 am
Posts: 11
Location: Italy
Thank you very much! So, I think that the only solution is to make stack work only in 16bytes boundaries... Maybe by storing the not 16byte aligned pushed data in a qword location in Memory, and "emulating" push and pop to make them always work in 16byte boundaries. Or simpler by storing data only in the lower part of those 16bytes... But that seems really a bad idea

_________________
You learn more by a single triple fault than by reading the whole Intel specification...


Top
 Profile  
 
 Post subject: Re: INT instruction stack behavior in x86-64 (Bochs)
PostPosted: Sat Aug 05, 2017 4:22 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
It's more conventional to pass parameters to a system call in registers rather than on the stack.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 159 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