system calls
system calls
how do you guys do system calls ?
with interrupts ?
if so, how do you cause the interrupt from c code ?
any links would be helpful as well
with interrupts ?
if so, how do you cause the interrupt from c code ?
any links would be helpful as well
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:system calls
On IA-32 systems, you have 3 techniques to implement system calls:
(off-topic: see !? i became a moderator
)
- ol' good INT n instruction (n = 21h for DOS, n = 0x80 for linux): the parameters must fit within the registers, but the processing is pretty slow and can be hardly tuned for one or another program (thus every process will receive the same API) and n must be a program constant.
- call gates: the parameters may be on the stack (a stack frame copy will occur), but for performance, they're likely to feel better in registers. You can give distinct processing to distinct process by putting the gate descriptor in the process's LDT.
- system-call infrastructure available on P-II+ and K6-II+, which is a fast interrupt call (through systar registers a.f.a.i.k), but which will impose restrictions on your system design (like CS and DS restrictions, etc.)
(off-topic: see !? i became a moderator

Re:system calls
how would i cause an interrupt from c code
i try asm("int 0x30") which i have interrupt 0x30 set up for a function....i do know how to do that since i have interrupts working for timer, keyboard, and floppy
...but when i try that asm("int 0x30") in my code, the compiler gives me errors
Error: suffix or operands invalid for int
and also, what is the best way to pass variables to the isr ? put them in registers, or push them on the stack ? Like variables that determine the sub-function of the interrupt...(i.e should i be printing a string, or just a char)
i try asm("int 0x30") which i have interrupt 0x30 set up for a function....i do know how to do that since i have interrupts working for timer, keyboard, and floppy
...but when i try that asm("int 0x30") in my code, the compiler gives me errors
Error: suffix or operands invalid for int
and also, what is the best way to pass variables to the isr ? put them in registers, or push them on the stack ? Like variables that determine the sub-function of the interrupt...(i.e should i be printing a string, or just a char)
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:system calls
that's because "int 0x30" is AT&T syntax for "int [0x30]" in Intel ... you should be using "int $0x30" ...ncsu121978 wrote: how would i cause an interrupt from c code
i try asm("int 0x30") which i have interrupt 0x30 set up for a function....i do know how to do that since i have interrupts working for timer, keyboard, and floppy
...but when i try that asm("int 0x30") in my code, the compiler gives me errors
Error: suffix or operands invalid for int
through registers, definitely, because your kernel code will hardly access to your user-level stack ...and also, what is the best way to pass variables to the isr ? put them in registers, or push them on the stack ? Like variables that determine the sub-function of the interrupt...(i.e should i be printing a string, or just a char)
see
http://cvs.sourceforge.net/cgi-bin/view ... cvs-markup
for a quick syscalls support header...
Re:system calls
let me see if i understand that code correctly
__scbegin(4,dword p1, dword p2, dword p3, dword p4)
i could basically call that from within my user function...or a library linked to my user program...and it will call the int 0x30 and pass to it the 4 variables in registers denoted by b, c, d, and S....
so then in my isr, i will need to get the values out of these registers into standard c variables (unless I write my isr in asm which i'm not) and then can do my work. In the isr, the return value needs to be placed in EAX and then in the user function or library i would extract the return falue from EAX.
Do i have this right ?
And I assume that I will need to push all those registers before I put in the user code/library before i put the variables into them.
__scbegin(4,dword p1, dword p2, dword p3, dword p4)
i could basically call that from within my user function...or a library linked to my user program...and it will call the int 0x30 and pass to it the 4 variables in registers denoted by b, c, d, and S....
so then in my isr, i will need to get the values out of these registers into standard c variables (unless I write my isr in asm which i'm not) and then can do my work. In the isr, the return value needs to be placed in EAX and then in the user function or library i would extract the return falue from EAX.
Do i have this right ?
And I assume that I will need to push all those registers before I put in the user code/library before i put the variables into them.
Re:system calls
while working out my system call to print a string to the screen i realized something.
i was passing the address of the start of the string to print in EAX, then causing the interrupt
in the irs, i retrieved the address out of the EAX register and was trying to print
the string.....it gave me garbage, so I kept looking over the code thinking I had made
a small error somewhere....well I did and I didn't. I just forgot the address translation.
Since the user program is running in different address space then the kernel (which actual does the printing for now)...
the kernel uses flat memory (ie 0 is mapped to 0 physical and 1234 is mapped to 1234 physical),
while the user program is mapped to 16 MB physical. So in my isr, I need to add
16MB onto the address that was passed via EAX to get the adress location of the string relative to how the kernel would view it.
That is just a pit fall i thought i would mention so that someone else might not step in it like i did.
Still another question however: what all registers do I need to push and save when I cause the interrupt ?
Right now I only have one process running so it is not multi-process or multi-threaded.
When I move to multi-process.....what registers should I push and save before causing the interrupt ?
i was passing the address of the start of the string to print in EAX, then causing the interrupt
in the irs, i retrieved the address out of the EAX register and was trying to print
the string.....it gave me garbage, so I kept looking over the code thinking I had made
a small error somewhere....well I did and I didn't. I just forgot the address translation.
Since the user program is running in different address space then the kernel (which actual does the printing for now)...
the kernel uses flat memory (ie 0 is mapped to 0 physical and 1234 is mapped to 1234 physical),
while the user program is mapped to 16 MB physical. So in my isr, I need to add
16MB onto the address that was passed via EAX to get the adress location of the string relative to how the kernel would view it.
That is just a pit fall i thought i would mention so that someone else might not step in it like i did.
Still another question however: what all registers do I need to push and save when I cause the interrupt ?
Right now I only have one process running so it is not multi-process or multi-threaded.
When I move to multi-process.....what registers should I push and save before causing the interrupt ?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:system calls
as a general rule, you should always push every register your interrupt service is likely to change (i.e. all general & segment registers).
btw, before relying on some pointer the user passes, you should check it doesn't go beyond the segment arrays... this isn't that important if the buffer is just being read (though you would care if the buffer hold someone else's password
, but it is mandatory before the kernel write to a user-buffer.
Don't let your OS be fooled by some hand-made pointer
btw, before relying on some pointer the user passes, you should check it doesn't go beyond the segment arrays... this isn't that important if the buffer is just being read (though you would care if the buffer hold someone else's password

Don't let your OS be fooled by some hand-made pointer

Re:system calls
You can also use RAM or other memory for system calles.
I.e. put some data somewhere in RAM ( the syscall ) or you could use the "syscall" in processors. But, the SYSCALL works differently on AMD and Intel processors
I.e. put some data somewhere in RAM ( the syscall ) or you could use the "syscall" in processors. But, the SYSCALL works differently on AMD and Intel processors

Re:system calls
Once you go multi-process, you won't be able to translate an address just by adding a fixed offset to the user-supplied pointer. Each process will be loaded at a different physical address.
You may want to consider designating a shared memory page (or pages) for passing syscall data as alluded to by Tom.
I still haven't worked out just how I want to handle this in my OS. I had run into the exact same problem you did and wound up severely flattening my forhead with the palm of my hand when I figured out what was wrong
You may want to consider designating a shared memory page (or pages) for passing syscall data as alluded to by Tom.
I still haven't worked out just how I want to handle this in my OS. I had run into the exact same problem you did and wound up severely flattening my forhead with the palm of my hand when I figured out what was wrong

Re:system calls
well.....seeing as how the operatig system will know what physical address the program is loaded at....why cant i just use the add offset ?
When my operating system loads an executable file (format is still up for debate), it will keep track of where it was loaded at
When my operating system loads an executable file (format is still up for debate), it will keep track of where it was loaded at
Re:system calls
How does your OS know which process is calling it? Without some way to uniquely identify a process, there's no way for the syscall handler to know which process made the syscall.
Now, you could assign each process a unique process id and have the syscall function pass that id to the syscall handler. Then the handler could do a table lookup to find the load address for the given process id...
Now, you could assign each process a unique process id and have the syscall function pass that id to the syscall handler. Then the handler could do a table lookup to find the load address for the given process id...
Re:system calls
There is multi-tasking syscall info in the Minux source code...but I can't read the book I bought [ Operating Systems: Design and implementation ] because i'm allergic to it :-\
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:system calls
A very simple way to know it is to look at the page directory base (PDBR) which should be unique (unless you have several process in the same address space).Dave Hunt wrote: How does your OS know which process is calling it? Without some way to uniquely identify a process, there's no way for the syscall handler to know which process made the syscall.
Hmm ... i'm not sure i get the point, but if you're suggesting the USER code will pass the PID to the kernel, i'm afraid you're going to experience very weird things with your OS.Now, you could assign each process a unique process id and have the syscall function pass that id to the syscall handler. Then the handler could do a table lookup to find the load address for the given process id...
A trick i used (mainly thanks to the way i set up stacks) is to use the stack segment's limit to identify a region of thread-specific datas quickly (called GLOCAL variables, in Tanenbaum terminology):
- All my kernel stacks have a base = to kernel data segment base
- My kernel stacks are set up expand-down and their limit matches the "stack overflow" address.
- When you get the limit for the stack segment (mov cx,ss ; lsl ecx), it gives you the "absolute-top-of-stack" address for the current thread, where a small memory area is allocated to store thread-specific variables such as errno, display buffer for this thread, pointer to the Thread structure (which itself has a pointer to its owner process and to the TSS under use), the current CPU identification, etc.
I guarantee this saved a *lot* of overhead while multithreading, simply because i know if something must be thread-safe and will be hardly shared (because a semwait() will cost too much), i just need to make it glocal
Re:system calls
Interrupts are slow for syscalls....I don't think i'm adding even a optional int syscall for FritzOS.