[Prev][Next][Index][Thread]
Re: OSKit & processes
> Since OSkit does not support processes directly, I decided I should
>give it
>a try and implement some of it myself. One of the easy ways is to use TSS and
>let the CPU handle all the state saving.
This is the fastest way as well, unless you are not planning to use paging.
>I can easily put a task gate in the IDT, but how can I do an "iretd" from
>a TSS
>exception/interrupt handler?
I assume you mean from the timer ISR... the scheduler is hooked to that.
>By coding it by hand, i.e. asm("iretd") or however gas requires?
>I don't think this should work, since the compiler inevitably places some
>"push"-es on the entry of the function and messes stacks. When I was fiddling
>with NASM and Visual C++ to make a simple 32-bit protected kernel, things were
>easy, because VC++ does _very_ simple code, and was easy to disassemble
>and see
>what it does in terms of asm instructions. Since I cannot do that here, and
>base_trap_* stuff obviously cannot handle task gates, and I do not want to
>make
>a software task switch, what should I do?
You need to make an assembly stub for interrupt handlers. You can do this
by inserting an asm() statement in top-level code (ie not in a function.)
My stubs look more or less like this:
asm (
".globl ISR_stub \n" /* Declare the stub as a global symbol */
"ISR_stub: \n" /* ISR stub starts here: */
" pushl %eax \n" /* Save the registers that GCC may */
" pushl %ecx \n" /* clobber. If GCC uses any other regs, */
" pushl %edx \n" /* it'll save and restore them itself */
" pushw %ds \n" /* Save the user data segement */
" pushw %ss \n" /* Set the kernel data segment (%ss is */
" popw %ds \n" /* always valid, ss0 in the TSS) */
" call ISR_c_code \n" /* Call the C ISR code */
" popw %ds \n" /* Restore user data segment */
" popl %edx \n" /* Restore clobbered registers */
" popl %ecx \n"
" popl %eax \n"
" iret \n" /* Return from interrupt */
);
Alternatively, you can put this in a separate .S file, compile with as and
link it in.
PS, you could also use a C-style function directly, as long as you start by
setting up the user %ds correctly and saving the registers. Just put
asm("iret") at the end. Don't worry about stack cleanup, the processor
doesn't remember the kernel %esp anyway after you iret. Your code will be
more portable, though, if you use stubs like I do.
>BTW, task switching can be very easily implemented this way, just change
>the back_link field in the kernel's TSS and iretd, that's all...
> Any advice? 10x in advance.
Hmmm... I've never done it this way, I don't know whether it works (doesn't
sound like it will to me, though I can't really point to why...) The usual
method is:
asm("ljmp %0,$0"::"g" (next_task_TSS_selector)); /* Do task switch */
Hope this helps...
Ramon
---
Ramon van Handel <vhandel@chem.vu.nl>
Chemistry Student, OS Programmer and all-round Weirdo
The ant has made himself illustrious / Through constant industry industrious.
So what? Would you be calm and placid / If you were full of formic acid?
(Ogden Nash)