x86_64-ISR-Register:
So i have a struct for storing register values during an interrupt:
Code: Select all
namespace CPU
{
typedef struct{
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rbp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((__packed__)) State;
}
Code: Select all
__attribute__((interrupt)) void LVT_Timer(CPU::State *state)
{
Interrupt::APIC::Write(APIC_EOI, 0);
}
syscall arguments:
Since i have a x86_64-kernel, i'd like to use the syscall instruction for my syscalls. The handler should look like that:
Code: Select all
void* Handler(uint64_t iCall, void* OtherArguments)
{
return (*Handlers[iCall])(OtherArguments);
}
My problem is: How do i pass arguments? Especially long arguments like a string or a char-array? And most importantly: How do i pass them in C/C++?
As far as i know, Linux passes arguments through the stack. But how does Linux handle arrays as arguments?
The simplest and most secure way would be to pass a pointer to an area where all arguments are (=> struct pointer) and let the (*Handlers[iCall]) do the deencapsulation, wouldn't it? But how do i handle different structs with different sizes?
So could i do something like that:
Usermode:
Code: Select all
namespace System
{
void* Syscall(uint64_t iCall, void* OtherArguments)
{
asm volatile("syscall");
//return?
}
}
Code: Select all
void Handler(uint64_t iCall, void* OtherArguments)
{
(*Handlers[iCall])(OtherArguments);
//return (*Handlers[iCall])(OtherArguments); <= That's stupid, see EDIT2
}
EDIT:
Or i could do something like that, right?
Code: Select all
typedef struct
{
uint64_t value1, value2;
} __attribute__((__packed__)) Testing;
Handlers[0] = &Test;
void* Test(void* OtherArguments)
{
Testing *Pointer = OtherArguments;
Pointer->value1 = 0x1;
}
I just saw that i wanted to exit the syscall with a normal return... fail^^
So how do i write the sysret? Would it be sufficient to do the following (without saving the stack pointers):
Code: Select all
void Handler(uint64_t iCall, void* OtherArguments)
{
asm volatile("push %rcx");
(*Handlers[iCall])(OtherArguments);
asm volatile("pop %rcx");
asm volatile("sysret");
}