Return Value from Syscall
Return Value from Syscall
I use GCC inline assembly to call syscalls, but I can get the right return value. I have readed that the return value stored in EAX. but I receive what I have put on EAX before I call the interrupt.
here is the code which call Sys_read
__asm__ __volatile__(
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%eax;"
"mov %1, %%ebx;"
"mov $1, %%ecx;"
"mov $1, %%eax;"
"int $0x80 ;"
"movl %%eax, %0;"
:"=r"(ret):"r"(c)
);
I receive allways 1 as return value, but I am sure the return value should be -1.
here is the code which call Sys_read
__asm__ __volatile__(
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%eax;"
"mov %1, %%ebx;"
"mov $1, %%ecx;"
"mov $1, %%eax;"
"int $0x80 ;"
"movl %%eax, %0;"
:"=r"(ret):"r"(c)
);
I receive allways 1 as return value, but I am sure the return value should be -1.
Re:Return Value from Syscall
hi,
Does your syscall handler puts proper values to the eax at the end of syscall.
eg,
syscall_handler:
if syscall fails,
movl $-1, %eax
...
iret
also, you can send the value directly.
__asm__ __volatile__(
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%eax;"
"mov %1, %%ebx;"
"mov $1, %%ecx;"
"mov $1, %%eax;"
"int $0x80 ;"
:"=a"(ret):"r"(c)
);
Does your syscall handler puts proper values to the eax at the end of syscall.
eg,
syscall_handler:
if syscall fails,
movl $-1, %eax
...
iret
also, you can send the value directly.
__asm__ __volatile__(
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%eax;"
"mov %1, %%ebx;"
"mov $1, %%ecx;"
"mov $1, %%eax;"
"int $0x80 ;"
:"=a"(ret):"r"(c)
);
Re:Return Value from Syscall
I dont think my syscall handler done that.
I am not Assembly hacher, there for I have used for IDT and the routines for Interrupt this code:
push byte 0 ; ( 0) fake error code
PUSHB %1 ; ( 2) exception number
push gs ; ( 4) push segment registers
push fs ; ( 6)
push es ; (
push ds ; ( 9)
pusha ; (10) push GP registers
mov ax,LINEAR_DATA_SEL ; (11) put known-good values...
mov ds,eax ; (15) ...in segment registers
mov es,eax ; (17)
mov fs,eax ; (19)
mov gs,eax ; (21)
mov eax,esp ; (23)
push eax ; (25) push pointer to regs_t
.1:
; setvect() changes the operand of the CALL instruction at run-time,
; so we need its location = 27 bytes from start of stub. We also want
; the CALL to use absolute addressing instead of EIP-relative, so:
mov eax,fault ; (26)
call eax ; (31)
jmp all_ints ; (33)
then I use setvect() to change the call statement at runtime to call syscall function in my kernel, when 0X80 occure. as see here after syscall has been called then I should return to original function which has been interrupted by CPU. this the function of all_ints routine :
all_ints:
pop eax
popa ; pop GP registers
pop ds ; pop segment registers
pop es
pop fs
pop gs
add esp,8 ; drop exception number and error code
iret
I have taken a look to the assembly code of the syscall and gcc store the return value in eax. but it like the all_ints routine pop the old eax value.
I am not Assembly hacher, there for I have used for IDT and the routines for Interrupt this code:
push byte 0 ; ( 0) fake error code
PUSHB %1 ; ( 2) exception number
push gs ; ( 4) push segment registers
push fs ; ( 6)
push es ; (
push ds ; ( 9)
pusha ; (10) push GP registers
mov ax,LINEAR_DATA_SEL ; (11) put known-good values...
mov ds,eax ; (15) ...in segment registers
mov es,eax ; (17)
mov fs,eax ; (19)
mov gs,eax ; (21)
mov eax,esp ; (23)
push eax ; (25) push pointer to regs_t
.1:
; setvect() changes the operand of the CALL instruction at run-time,
; so we need its location = 27 bytes from start of stub. We also want
; the CALL to use absolute addressing instead of EIP-relative, so:
mov eax,fault ; (26)
call eax ; (31)
jmp all_ints ; (33)
then I use setvect() to change the call statement at runtime to call syscall function in my kernel, when 0X80 occure. as see here after syscall has been called then I should return to original function which has been interrupted by CPU. this the function of all_ints routine :
all_ints:
pop eax
popa ; pop GP registers
pop ds ; pop segment registers
pop es
pop fs
pop gs
add esp,8 ; drop exception number and error code
iret
I have taken a look to the assembly code of the syscall and gcc store the return value in eax. but it like the all_ints routine pop the old eax value.
Re:Return Value from Syscall
what about placing the return code in the eax-placeholder in regs_t - you know, the isr stack frame pushed/popped to/from the ring0 stack.
you can access it in c as simple as:
eax is popped from the stack with popad, and voila, your returncode is present where it is usually expected.
If writing a microkernel, the returncode is delivered simply by sending a message back to the calling process - which is expected to receive().
hth&ccw
you can access it in c as simple as:
Code: Select all
regs_t *regs;
regs=(regs_t *)current_process->esp0;
regs->eax= syscall_retcode;
If writing a microkernel, the returncode is delivered simply by sending a message back to the calling process - which is expected to receive().
hth&ccw
Re:Return Value from Syscall
is it (in similar context) possible to use
?
Code: Select all
struct regs {
uint32 edi, esi, ebp, esp, ebx, edx, ecx, pad, eax;
}
void something(struct regs sth) {
regs.eax = -1;
}
do_call:
push eax
pusha
call something
popa
pop eax
iret
Re:Return Value from Syscall
this would overwrite the value of eax - as stored in regs in the isr-prologue and restored after isr-execution in the isr-epilogue with the value pushed on the stack at the beginning of the isr-prologue, as you show it.
to be exactly, it would overwrite the -1 you put onto the stack with void something.
btw: this works as long as we remain on the same stack, doesn't it? you can access the elements of it as function parameters - which are placed on the stack. Just that I understand correctly, what happens there.
to be exactly, it would overwrite the -1 you put onto the stack with void something.
btw: this works as long as we remain on the same stack, doesn't it? you can access the elements of it as function parameters - which are placed on the stack. Just that I understand correctly, what happens there.
Re:Return Value from Syscall
to clarify: popa (popad) and pusha(pushad)
handle the "general purpose" registers of the processor:
eax,ebx,ecx,edx,esi,edi,ebp,esp
that's why one usually doesnt need to handle eax specially in an isr stub.
handle the "general purpose" registers of the processor:
eax,ebx,ecx,edx,esi,edi,ebp,esp
that's why one usually doesnt need to handle eax specially in an isr stub.
Re:Return Value from Syscall
take look to this code. the interrupt handler for 0X80 call syscall, which call the correct sys call from sys_call_table
then I store the return value in regs->eax. as you mentionded above.
but still i don't receive the return value
then I store the return value in regs->eax. as you mentionded above.
Code: Select all
unsigned long sys_call_table[] = {sys_write, sys_read};
void syscall(regs_t *regs)
{
//unsigned long fnc_addr;
//fnc_addr = (unsigned long)sys_write ;
disable();
__asm__ __volatile__(
"mov %1, %%ebx;"
"mov %2, %%ecx;"
"pushl %%ecx ;"
"pushl %%ebx ;"
"call *sys_call_table(,%3, 4) ;"
"popl %%ebx;"
"popl %%ecx; "
:"=a" (regs->eax):"r"(regs->ebx), "r"(regs->ecx), "r" (regs->eax)
);
enable();
}
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Return Value from Syscall
I'm not good at reading gcc inline assembly.
ARe you sure you pass the correct pointer to this function?
where do you manipulate eax of the process/task issueing the system call? are you sure, you are still operating in the correct stack frame? What does your stack frame look like? do you have a definition of it at hands?
Mark: just place the return code in regs.eax of the current process/task. Upon Iret - in the isr epilogue - eax is per magic wand provided with the return code, as you want it.
HtH
ARe you sure you pass the correct pointer to this function?
where do you manipulate eax of the process/task issueing the system call? are you sure, you are still operating in the correct stack frame? What does your stack frame look like? do you have a definition of it at hands?
Mark: just place the return code in regs.eax of the current process/task. Upon Iret - in the isr epilogue - eax is per magic wand provided with the return code, as you want it.
HtH
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Return Value from Syscall
I am sure I pass correct pointer to syscall, because the task push the number of system call (for examble 0 for system write) and that work very fine. I have define three task one of them work in user mode (am image loaded via grub then) and it call sys_write to write some text on screen.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Return Value from Syscall
In your code for the isr_stub i see
does fault() have a proper declaration/definition to handle the pointer to the stack of the interrupted process?
well ... you have an int 0x80 for software interrupts. You know, it is no sense to put parameters for a system call via int xx interface onto the user stack. You need to pass them via registers.
Code: Select all
mov eax,esp
push eax ;saving position of esp
mov eax,fault ;(sure, you call *fault(regs_t *regs), not
syscall(regs_t *regs)?
well ... you have an int 0x80 for software interrupts. You know, it is no sense to put parameters for a system call via int xx interface onto the user stack. You need to pass them via registers.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Return Value from Syscall
fault function is the default for all Interrupt routines. but I can change it with another function called "setvect()" which change the call to whatever I want.
in runtime I change the interrput routine for 0x80 to call syscall (not fault).
seconldy I don't use stack to send parameters to syscall, I use registers.
in runtime I change the interrput routine for 0x80 to call syscall (not fault).
seconldy I don't use stack to send parameters to syscall, I use registers.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Return Value from Syscall
Ok, seems like I've misread some of your statements. Pls take my apologies for this.
But once again:
do you pass the pointer to regs, which you are passing to fault() to syscall after changing the call?
To be more exact, could you post the relevant functions?
1: call to fault(regs_t *regs). fault shall get the pointer to esp(regs).
2: fault redirects the call to syscall, if int 0x80 's been invoked: if(int0x80) syscall(regs).
I'd like to check exactly this passing of the pointer to regs.
But once again:
do you pass the pointer to regs, which you are passing to fault() to syscall after changing the call?
To be more exact, could you post the relevant functions?
1: call to fault(regs_t *regs). fault shall get the pointer to esp(regs).
2: fault redirects the call to syscall, if int 0x80 's been invoked: if(int0x80) syscall(regs).
I'd like to check exactly this passing of the pointer to regs.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Return Value from Syscall
I have put above the Interrupt routine for all interrupt (see my second post), then this function
change "move eax, fault" to whatever you give it to call ( for examble "move eax, syscall" and it change also the Access byte on IDT. all these done when initialize the the system.
at startup I define 254 function for interrupt routines ( using assembly), which in default call fault routine. then (in c code) i call setvect() to replace the fault routine with another routine to handle the interrupt. exactly I replace it for (IRQ6 floppy) Timer and System call. when others Interrput occure the cpu call fault routine
Code: Select all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: setvect
; action: writes interrupt vector
; in: [EBP + 12] = vector number,
; vector stored at address given by [EBP + 8]
; out: (nothing)
; modifies: EAX, EDX
; minimum CPU: '386+
; notes: C prototype:
; typedef struct
; { unsigned access_byte, eip; } vector_t;
; getvect(vector_t *v, unsigned vect_num);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXP setvect
push ebp
mov ebp,esp
push esi
push ebx
mov esi,[ebp + 8]
; store access byte in IDT[i]
mov eax,[esi + 0]
xor ebx,ebx
mov bl,[ebp + 12]
shl ebx,3
mov [idt + ebx + 5],al
; store handler address in stub
mov eax,isr1
sub eax,isr0 ; assume stub size < 256 bytes
mul byte [ebp + 12]
mov ebx,eax
add ebx,isr0
mov eax,[esi + 4]
mov [ebx + (isr0.1 - isr0 + 1)],eax
pop ebx
pop esi
pop ebp
ret
at startup I define 254 function for interrupt routines ( using assembly), which in default call fault routine. then (in c code) i call setvect() to replace the fault routine with another routine to handle the interrupt. exactly I replace it for (IRQ6 floppy) Timer and System call. when others Interrput occure the cpu call fault routine
Code: Select all
void syscall(regs_t *regs)
{
disable();
__asm__ __volatile__(
"mov %1, %%ebx;"
"mov %2, %%ecx;"
"pushl %%ecx ;"
"pushl %%ebx ;"
"call *sys_call_table(,%3, 4) ;"
"popl %%ebx;"
"popl %%ecx; "
:"=a" (regs->eax):"r"(regs->ebx), "r"(regs->ecx), "r" (regs->eax)
);
enable();
}
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Return Value from Syscall
Now, I see it better. sorry asking so much question.
I have a proposal, since I am not sure whether "=a"(regs->eax) does exactly what you want it to do. That's interpreted and formed to assembly by the compiler.
What about:
:"=a"(regs->eax) means according the gcc inline asm howto, that this operand is stored in eax. How to determine whether it is an address or a value in AT&T syntax I don't know, so take my addition as a suggestion. Nevertheless, I suppose you *assign* the return value to the field in regs.
I have a proposal, since I am not sure whether "=a"(regs->eax) does exactly what you want it to do. That's interpreted and formed to assembly by the compiler.
What about:
Code: Select all
__asm__ __volatile__(
"mov %1, %%ebx;"
"mov %2, %%ecx;"
"pushl %%ecx ;"
"pushl %%ebx ;"
"call *sys_call_table(,%3, 4) ;"
"mov %0,%%eax;" //added by me!!
"popl %%ebx;"
"popl %%ecx; "
:"=a" (regs->eax):"r"(regs->ebx), "r"(regs->ecx), "r" (regs->eax)
);
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image