SYSENTER/SYSEXIT

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.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Because of syntax. I want nice-looking, clean semantics. Using your method a syscall would look something like

Code: Select all

DO_SYSCALL(class::method, &classInstance);
and I don't like the look of that. The only difference between your and my methods is that my sysenter code is called after gcc creates the stack frame for a member function.

Yes, it needs a shared entry point. The shared entry code copies the user's stackframe over to the kernel stack, and jumps back to a point specified in eax. (Which will generally just call 'ret', but this doesn't always have to be the case).

JamesM
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

You are making zero sense at the moment. I am lost.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Well, I can't work out what I've lost you on, so I'll just post my code :P

Code: Select all

[GLOBAL fastSyscall]
fastSyscall:
  mov ecx, ebp          ; Current stack frame start.
  mov ebx, ebp          ; ebx = stack frame size
  sub ebx, esp          ;     = (ebp-esp)
  
  mov eax, .syscall_end ; eax = EIP to return to.

  sysenter              ; Make syscall.

.syscall_end:
  ret

; Takes one argument - esp0 - the start (upper limit) of the kernel stack.
[GLOBAL fastSysexit]
fastSysexit:
  mov esp, [esp-4]      ; Dereference parameter - esp = *(esp0) - go back to the
                        ; beginning of our stack frame and dereference what we 
                        ; find, which will be the esp pushed in the handler.
  pop ebp               ; Return ebp to what it was before we were called.
  pop edx               ; EDX = EIP return pointer
  mov ecx, esp          ; Return ESP
  jmp $
  sysexit

[GLOBAL fastSyscallHandler]
fastSyscallHandler:
  push ecx              ; Push the old stack pointer on the new stack.
  
  mov esi, 0x20
  add ecx, 0x20
.loop:                  ; copy some of the stack before the stack frame base
  mov edx, [ecx]  ; to make sure we copy any arguments passed to the
  mov [esp], edx  ; function.
  sub esp, 0x4
  sub ecx, 0x4
  sub esi, 0x4
  jnz .loop
  
  mov ebp, esp          ; Set up our new base pointer
  mov edx, ebx          ; store the frame size.
  mov ebx, ebp          ; EBX = stack base ptr -stack frame size.
  sub ebx, edx          ; do the subtraction.

.loop2:
  mov edx, [ecx]        ; Copy [ecx] to [esp] ( copying stack frame to kernelspace )
  mov [esp], edx
  sub esp, 0x4          ; Next word, working down the stack.
  sub ecx, 0x4          ; Next work, working down the stack.
  cmp esp, ebx          ; do while esp < frame size + base ptr
  jnz .loop2
  
  mov edx, [ecx]        ; copy one more.
  mov [esp], edx
  
  jmp eax

Code: Select all

class C
{
  int a_member_func(int a)
  {
    START_KERNEL;

   bleh

   END_KERNEL;
  }
}
This way you can call a class' member function from user space or kernel space transparently. Because the ring-change-if-nessecary code is inside the member function, you can be in ring0 or ring3 and call the same function with the same semantics. It looks cleaner.

It is also not member-function specific, it can be used in __cdecl functions, where your method (pushing the this pointer and dereferencing the vtable) can't. It's just a design decision I made. I really value your input though, I debated it a lot in my head before I decided on anything.

Thanks!

JamesM
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

Oh. Ok. I get it. :P
Post Reply