OSDev.org

The Place to Start for Operating System Developers
It is currently Wed May 15, 2024 8:23 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 73 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 12:21 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

AR wrote:
Why exactly do you need more than one return value? I usually use "void" as the return value for the C function to the interrupt stub, I don't see what exactly you're referring to.


For IRQ handlers this is indeed the case. Unfortunately IRQ handler's are not (or at least should not) be the only place where a task switch may occur. Any kernel function that causes a task to be blocked (wait_for_message(), getchar(), sleep(), fopen(), etc) also causes a task switch. This implies that the entire kernel API is also effected.

AR wrote:
I believe the one return value is built on the mathematical principles of an algebraic equation. eg: m = f(b), m = a + 3b + 2. In maths there is always only one result from an equation, all languages that I know which are higher than assembly seem to be built on this principle which basically means that any and all algorithms can be broken down to components that will only require 1 return value. Of course in computers there are more than just numbers (strings, images) but the instances where multiple return values are absolutely necessary don't come around that often.


I guess you're right - functional languages may have been built on the mathematical principles of an algebraic equation, which are inappropriate, unnecessary and just plain broken. The ugly hacks that have evolved to get around this limitation seem to agree with me. Consider 2 simple C library functions:

With 2 return values:

Code:
long int strtol (const char *restrict string, char **restrict tailptr, int base);


Or with a hidden return value, where "errno" is also returned behind the callers back (which for most older C libraries, causes re-entrancy problems for anything multi-threaded):

Code:
FILE * fopen (const char *filename, const char *opentype);


Of course usually the single return value is mangled to serve dual purposes. A typical example of this is "malloc()", where instead of returning a status code and an address it combines both. This works, but means that returning a reason why the function failed is impossible. Did it fail because memory ran out, or because the heap has been corrupted, or because I accidentallty asked it to allocate 3.5 GB? Sorry - no way to tell.

The instances where multiple return values are used depends on the programmer and the language. For a programmer who is conditioned to work within the limitations of a HLL language, it may be rare.

For my assembly code (and code designed for or written in assembly) it happens quite frequently and results in better code (from the CPU's perspective). For examples of functions where the design was not limited by broken compilers, see the BIOS functions (where returning multiple values is very common).


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 5:48 am 
ok, would if this was the first tick:
Code:
_task_timer
    cld
    pushad
    push ds
    push es
    push fs
    push gs
;    mov eax,[p]
;    mov [eax],esp
;    lea eax,[kstackend]
;    mov esp,eax
    mov eax, _timer_handler
    call eax
;    mov eax,[p]
;    mov esp,[eax]
;    mov ebx,[eax+8]
;    mov [sys_tss+4],ebx
    mov al,0x20
    out 0x20,al
    pop gs
    pop fs
    pop es
    pop ds
    popad
    iretd

it would get the kernel stack but how do i put that for later or how do i get it to do it only the first time???


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 9:35 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

I not sure I completely understand what the code is meant to do (hint: comments are good). For example, what are [p] and [kstackend], and what's at [sys_tss+4]?

The name [kstackend] makes me wonder if it's the "kernel stack top" and if you're intending to have a single kernel stack that's shared by all tasks (which may be reasonable, unless it's a monolithic kernel or you might want to support multiple CPUs one day). Even if you are intending to use a single kernel stack for all tasks, that isn't the way to do it (you need the data that is pushed on the stack to return to the task and it must not be overwritten, and you wouldn't need to reset ESP0 in the TSS).

The name [p] tells me nothing, but from the way it's used I assume it's a pointer to a task information structure for the currently running task, and that any code that wants to cause a task switch changes this value to point to a different task (the task to switch to). If this is correct, then you'll have problems when you add address space switching to it because you'd need to know if the task that was running is the same as the task you're switching to (so you can avoid reloading CR3 and flushing TLB entries when it's not necessary). I see no way to do this comparison..

Also, the task switch code must go after the EOI.

Adding all this up gives something more like:

Code:
_task_timer
    cld
    pushad
    push ds
    push es
    push fs
    push gs

    ;Load new segment registers here???

    call _timer_handler

    mov al,0x20                      ;Do the EOI
    out 0x20,al

    mov eax,[current_task_pointer]   ;eax = address of current task structure
    mov ebx,[next_task_pointer]      ;ebx = address of new task structure
    cmp eax,ebx                      ;Is a task switch needed?
    je .doneTaskSwitch               ; no, skip it

    mov [eax],esp                    ;Save ESP in the current task structure
    mov esp,[eax]                    ;Load ESP from the new task structure
    mov ebx,[eax+TASK_ESP0]          ;Get ESP0 from the new task structure
    mov [sys_tss+TSS_ESP0],ebx       ;Set ESP0 in the TSS for the new task
    mov [current_task_pointer],ebx   ;The new task is now the current task
.doneTaskSwitch:

    pop gs
    pop fs
    pop es
    pop ds
    popad
    iretd


[continued]

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 9:43 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
[continued]

Of course you'll probably have the same code at the end of any IRQ handler that can cause a task switch, plus more copies in some of the exception handlers, and more copies for kernel API's exit/s. To make life easier why not do something like:

Code:
_task_timer
    cld
    pushad
    push ds
    push es
    push fs
    push gs

    ;Load new segment registers here???

    call _timer_handler

    mov al,0x20                      ;Do the EOI
    out 0x20,al

    call _do_task_switch

    pop gs
    pop fs
    pop es
    pop ds
    popad
    iretd


;Note: Registers must be saved on the stack, and interrupt must be disabled
;      before calling this routine.

_do_task_switch:
    mov eax,[current_task_pointer]   ;eax = address of current task structure
    mov ebx,[next_task_pointer]      ;ebx = address of new task structure
    cmp eax,ebx                      ;Is a task switch needed?
    je .doneTaskSwitch               ; no, skip it

    mov [eax],esp                    ;Save ESP in the current task structure
    mov esp,[eax]                    ;Load ESP from the new task structure
    mov ebx,[eax+TASK_ESP0]          ;Get ESP0 from the new task structure
    mov [sys_tss+TSS_ESP0],ebx       ;Set ESP0 in the TSS for the new task
    mov [current_task_pointer],ebx   ;The new task is now the current task
.doneTaskSwitch:
    ret


This will add about 12 cycles (the cost of a "call/ret"), but it'll save you more time than you'd think, especially when you're adding address space switching, FPU/MMX/SSE/SSE2 state saving, etc. It's also great for testing the rest of your scheduler - just put some dubugging stuff at the top of "_do_task_switch" that displays the current task number on the screen.

You can still convert it back into several different copies when the OS is working and you're ready to optimize everything (I'll bet you decide not to once you've got that far though)...

GLneo wrote:
it would get the kernel stack but how do i put that for later or how do i get it to do it only the first time???


Every time you create a new task, you must create a kernel stack that contains the values that the task switching code will pop off the stack. For the code above it could be EIP and nothing else. For the earlier version it would be all the general registers, all the segment registers, EIP, EFLAGS, CS, ESP and SS (not necessarily in that order though).

I'm also not sure if you want your OS to allow segment registers to be changed, or if they can be treated as constants. If they can be changed then you'd need to set them to values that the kernel expects just after saving them on the stack. If they are treated like constants, then there's no need to save them on the stack or restore them. Either way the code above isn't right yet...


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 10:29 am 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
Brendan, with all due respect, your advice on this matter confuses me. I think that it would also confuse newbies pretty badly.

You like assembler... I respect that. But I think as a consequence you just aren't seeing how things can be done easily and well in C, or why someone would want to use C...

Anyway, I'm 1000 miles away from my kernel's source code right now so I can't post any clarifying examples. I'll just try to talk through your example as best I can.

First of all, why do you think you can't pass parameters to and from the kernel in registers just because you're using C?

Code:
pusha ; Input parameters are saved on the stack here.
; etc....
; call C code to get the system timer tick...
call something...
mov esp, eax
; etc...
popa ; Puts output parameters in the caller's registers.
iret

// Somewhere else...
TrapFrame* get_timer_tick( TrapFrame* callerRegs )
{
    uint32_t someParam = callerRegs->ebx;  // For example...
    ...
    callerRegs->eax = system_timer_tick; // Return value
    return callerRegs; // Don't switch to another task.
}


Why is this so difficult? It seems to me you're assuming that implementing a kernel in C requires a C-like kernel API, or requires the use of C calling conventions in the kernel API. This just isn't true, as I've shown above.

<edit>
A few other things I found strange:

Quote:
So far the only benefit mentioned for this method is that it allows system code to be written without caring where in the code any task switches might be done (by forcing the task switch to be postponed until kernel exit). This itself can cause problems with some kernel functions (e.g. terminate a task), and can make a mess of interrupt latency - if an IRQ handler interrupts a kernel function then both can't cause a task switch with any sanity, and you end up disabling interrupts while any kernel code is being run (the kernel itself can't be interruptable or pre-emptable).


First, what problem with task termination are you seeing? You would just never switch to that task again, and de-allocate its kernel stack. I don't see a problem here.

Secondly, the bit about non-preemptability just isn't true either. It's true that you have to be choosy about switching tasks in an interrupt -- especially if you support nested interrupts. However, it's perfectly ok to switch tasks in the least-nested interrupt, even if it interrupt kernel code. You just have to make sure it didn't interrupt the scheduler or something else really critical. :)
</edit>

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 1:04 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

Colonel Kernel wrote:
Brendan, with all due respect, your advice on this matter confuses me. I think that it would also confuse newbies pretty badly.


It's a bad habit of mine that I try to avoid, and I may not have been able to simplify things to the point where an absolute beginner may understand them easily. However, complex topics are complex by nature - IMHO it would be difficult for anyone to explain all options that can effect scheduling and scheduler design without at least a little confusion (which seems to include a little confusion of my own).

Colonel Kernel wrote:
First of all, why do you think you can't pass parameters to and from the kernel in registers just because you're using C?


Hmm, mostly because I'm used to assembly calling assembly routines, C calling C functions, and assembly that pretends it's C in order to call C functions. I find your assembly language "trick" (passing the address of a structure, which happens to be the contents of the stack from the assembly stub) to be quite an elegant solution - it just didn't occur to me.

Converted to "what the CPU sees" and adding some of the assumption I made earlier (the call table, with EDI used for the function number rather than EAX), it becomes something like:

Code:
kernel_API_entry_point:
    cmp edi,MAX_FUNCTION_NUMBER
    ja .function_not_defined_error

    pusha
    mov eax,esp
    call [kernel_API_function_table + edi * 4]
    cmp eax,esp
    jne .noTaskSwitch
    mov esp,eax
    ; if ? mov cr3,? (skipped - reason for the branch)
    ; fxload/fxsave or set TS flag (skipped - reason for the branch)
.noTaskSwitch:
    popa
    iret

.function_not_defined_error:
    mov eax,ERROR_FUNCTION_NOT_DEFINED
    iretd


_get_timer_tick:
    mov eax,[esp+4]             ;eax = address of callerRegs structure
    mov ebx,[system_timer_tick]
    mov [eax+callerRegs._EBX]
    ret


It's almost as efficient as my prefered method. I did notice that for your version the kernel can't call the kernel API functions itself (i.e. without the assembly stub), while for my earlier attempts (both the in-elegant C version and the assembly version) it can, which isn't important for a such a simple function but for other larger functions it can be handy (depending on OS design - for e.g. I normally have several kernel threads that never use CPL=3 code where it's used often, while a small micro-kernel may never need it).

Colonel Kernel wrote:
First, what problem with task termination are you seeing? You would just never switch to that task again, and de-allocate its kernel stack. I don't see a problem here.


You de-allocate the kernel stack and then use the de-allocated kernel stack to return to the assembly stub where the task switch occurs? Perhaps you mean that you return from the function, do a task switch and then something happens in the future that causes the kernel to de-allocate the kernel stack, or maybe the assembly stub itself de-allocates the kernel stack during the task switch or...?

Quote:
Secondly, the bit about non-preemptability just isn't true either. It's true that you have to be choosy about switching tasks in an interrupt -- especially if you support nested interrupts. However, it's perfectly ok to switch tasks in the least-nested interrupt, even if it interrupt kernel code. You just have to make sure it didn't interrupt the scheduler or something else really critical. :)


Selectively non-preemptable and/or non-interruptable?

How about the page fault handler - how does that work considering it might terminate the task or need file IO?


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 3:55 pm 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
Brendan wrote:
You de-allocate the kernel stack and then use the de-allocated kernel stack to return to the assembly stub where the task switch occurs? Perhaps you mean that you return from the function, do a task switch and then something happens in the future that causes the kernel to de-allocate the kernel stack, or maybe the assembly stub itself de-allocates the kernel stack during the task switch or...?


ROFL... This is why I shouldn't be posting here while on vacation. :D You're quite right, the deallocation would have to happen later. You could always fudge the deallocated stack's registers to iret to the kernel's deallocation routine, or something like that... Haven't implemented it yet. :)

Quote:
How about the page fault handler - how does that work considering it might terminate the task or need file IO?


IMO, a microkernel shouldn't be doing file I/O. A monolithic kernel should "iret to a kernel-mode thread" the way NT does (in NT terms, lowering the IRQL from DISPATCH_LEVEL to APC_LEVEL). If the PF handler has to kill the task, see the solution proposed above.

Quote:
However, complex topics are complex by nature - IMHO it would be difficult for anyone to explain all options that can effect scheduling and scheduler design without at least a little confusion (which seems to include a little confusion of my own).


Complex topics are complex, but if you look closely enough they are really a set of interacting slightly-less complex topics. What's confused me a lot in the past is when I see a connection between two complex things where there really isn't a connection. In this case I think you connected C calling conventions with kernel calling conventions, which need not be related.

This is why I was asking all those weird questions last year about kernel-level abstractions for flow of control. :) If you can reason about these issues at a higher level, it becomes much easier to translate your ideas to other languages and talk about them with others. If I have time later I'll post some of my thoughts and terminology on these issues.

In the meantime, understanding IRQLs in NT is a good place to start -- what they are, how they work, and most importantly how they affect flow of control, pre-emptability and interruptibility in the kernel. "Inside Windows NT" has a lot of info on this. I also found studying the Minix source code to be quite useful, even though the implementation itself is a little yucky and limited.

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 5:19 pm 
well what i meant was: do i need to pop kernel data at a timer handler so i can save data???, what i want to know is at the very first time my kernel ticks the data it pushes will be my kernel's data, how do i store that for latter popping???


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 7:45 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

GLneo wrote:
well what i meant was: do i need to pop kernel data at a timer handler so i can save data???, what i want to know is at the very first time my kernel ticks the data it pushes will be my kernel's data, how do i store that for latter popping???


I'm probably not understanding the question properly - do you mean "How do I save ESP during a task switch, so that I can switch back to the same task later?"

If this is right, then your OS would need to keep track of the current task somehow (e.g. a global variable that contains the address of the current task's "task information structure"), so that you can store ESP into this "task information structure".


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 8:15 pm 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
GLneo wrote:
well what i meant was: do i need to pop kernel data at a timer handler so i can save data???, what i want to know is at the very first time my kernel ticks the data it pushes will be my kernel's data, how do i store that for latter popping???


The first time your timer ticks in ring 0, the data it pushes will be pushed on whatever stack you're using in ring 0. If you don't switch stacks (which you shouldn't if there are no tasks ready to run yet), then you'll be popping off that very same stack and everything will be ok. Why do you see a problem here?

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 12, 2005 8:56 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

Colonel Kernel wrote:
Complex topics are complex, but if you look closely enough they are really a set of interacting slightly-less complex topics. What's confused me a lot in the past is when I see a connection between two complex things where there really isn't a connection. In this case I think you connected C calling conventions with kernel calling conventions, which need not be related.


A set of interacting less complex/smaller topics, where you'd need to understand the interactions and each smaller topic, rather than a single large complex topic? This seems like the difference between one dozen and 6 pairs to me - it's the same quantity of "stuff" in the end.

There's a saying (or perhaps a chinese proverb) that I can't remember correctly - something about a butterfly on one side of the world flapping it's wings and indirectly causing a tidal wave on the other side of the world. I guess what I mean is that for OS development there's a lot of decisions that have consequences that aren't obvious. For example, choosing to use the protected mode interface for APM BIOS functions could effect whether or not the task switching code needs to save and restore segment registers (depending on a whole pile of things in-between).

However, I didn't connect C calling conventions with kernel calling conventions. From the post that I assume you're refering to:

Quote:
I will also assume that, for the kernel API, parameters are passed in registers through a software interrupt, which includes a "function number" that is used with a table to find the address of the kernel function to be executed. I'm making this assumption for a few reasons - it's almost exactly what Linux and my own OS does, and it's one of the cleanest, most efficient methods. I will also assume that all kernel functions return a 32 bit status code, such as "OK", "function not defined", "out of memory" or "time-out error". This is just my personal preference.


Followed by:

Quote:
The application would need this code to use the function:

Code:
Code:
  mov eax,GET_SYSTEM_TIMER_TICK
  mov ebx,ADDRESS_TO_STORE_STATUS
  mov ecx,ADDRESS_TO_STORE_TIMER_TICK
  int KERNEL_API_INTERRUPT
  cmp dword [ADDRESS_TO_STORE_STATUS],STATUS_OK
  jne .error
  mov eax,[ADDRESS_TO_STORE_STATUS]


As you can see, the application's code is passing parameters (pointers) to the kernel via. registers...

What I did do is fail to think of a more elegant way of implementing the interface between the assembly stub and the C functions - an oversight with consequences that weren't obvious to me at the time (consequences like passing pointers in registers instead of using the values pushed on the stack by the assembly stub).


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Tue Sep 13, 2005 6:06 am 
nope still not what i meant, ok, all the tutorials i see they do this:
Code:
push everything
mov esp, [kernel_esp]
pop everything; all kernels data
call task_switcher
push everything; kernels data
mov esp, [new_esp]
pop everthing
iret

but for the first time how do i get kernel data in the first place, so i can do things in the kernel, or am i just lost???, thx


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Tue Sep 13, 2005 9:01 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

GLneo wrote:
nope still not what i meant, ok, all the tutorials i see they do this:
Code:
push everything
mov esp, [kernel_esp]
pop everything; all kernels data
call task_switcher
push everything; kernels data
mov esp, [new_esp]
pop everthing
iret

but for the first time how do i get kernel data in the first place, so i can do things in the kernel, or am i just lost???, thx


I think we're both lost now! :)

Which tutorials have you been reading? The code above looks like it's switching from the CPL=0 stack (used by the CPU) to a different kernel stack, and the way they're using ESP doesn't make sense to me.

Forgetting this, usually before any task switching is started (even when the BIOS is booting before your OS is loaded), the CPU is already running one task. Also, when code is running it's state is stored in the CPU itself, not on any stack (or anywhere else).

Combining both of these, it means that you don't need to store the kernel's CPU state before the first task switch. You will need to create the structure/s that your scheduler uses though.


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Tue Sep 13, 2005 11:15 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

Ok, I realise that replying to my own post might be a sign of insanity, but I've been doing some research and think I've found the main reason why my advice isn't helping GLneo much...

From an earlier post:
GLneo wrote:
Code:
_task_timer
    cld
    pushad
    push ds
    push es
    push fs
    push gs
;    mov eax,[p]
;    mov [eax],esp
;    lea eax,[kstackend]
;    mov esp,eax
    mov eax, _timer_handler
    call eax
;    mov eax,[p]
;    mov esp,[eax]
;    mov ebx,[eax+8]
;    mov [sys_tss+4],ebx
    mov al,0x20
    out 0x20,al
    pop gs
    pop fs
    pop es
    pop ds
    popad
    iretd



This code matches the tutorial at http://www.osdever.net/tutorials/multit ... ?the_id=84 (and the link posted by Beyond Infinity, it's author :) ) almost identically. The macros used within this tutorial have comments :D, specifically:

Code:
   %macro REG_SAVE 0
      ;save all registers in the kernel-level stack of the process and switch to the kernel stack
        cld
        pushad
        push ds
        push es
        push fs
        push gs
        mov eax,[p] ;put the adress of the struct of CURRENT PROCESS in eax.(the CONTENT of pointer p)
        mov [eax],esp ;save esp in the location of esp in the CURRENT PROCESS-STRUCT.
        lea eax,[kstackend] ; switch to the kernel's own stack.
        mov esp,eax
        %endmacro


Unless my wits have completely failed me, this tutorial assumes a CPL=3 stack per task, a CPL=0 stack per task and a CPL=0 stack that's shared by all tasks. This is (IMHO) quite unusual, but explains a lot about previous discussion - my response to this was:

Brendan wrote:
I not sure I completely understand what the code is meant to do (hint: comments are good). For example, what are [p] and [kstackend], and what's at [sys_tss+4]?

The name [kstackend] makes me wonder if it's the "kernel stack top" and if you're intending to have a single kernel stack that's shared by all tasks (which may be reasonable, unless it's a monolithic kernel or you might want to support multiple CPUs one day). Even if you are intending to use a single kernel stack for all tasks, that isn't the way to do it (you need the data that is pushed on the stack to return to the task and it must not be overwritten, and you wouldn't need to reset ESP0 in the TSS).


Due to the missing comments I was guessing, and assumed it may be for an OS that uses a CPL=3 stack per task and a CPL=0 stack that's shared by all tasks (without the additional CPL=0 stack per task, which I still find "unusual").

Earlier, GLneo posted the following code:
GLneo wrote:
Code:
push everything
mov esp, [kernel_esp]
pop everything; all kernels data

call task_switcher

push everything; kernels data
mov esp, [new_esp]
pop everthing

iret


This version doesn't match any tutorial that I've been able to find, but (based on guess-work alone), I'm wondering if it originated from something that has a CPL=3 stack per task and a CPL=0 stack shared by all tasks (similar to the first tutorial, but without the additional CPL=0 stack per task that I found unusual). I could be completely wrong though...

The advice I've been giving is for an OS that uses a CPL=3 stack per task and a CPL=0 stack per task, where no stack is ever shared. This is the same as what my OS uses, roughly similar to what Linux uses (I don't want to confuse things more by discussing the more recent "4 KB kernel stack" patch/option), the same as Solaris (IIRC), is very similar to what Intel's hardware task switching does, and is IMHO far more common.

As far as I can tell, GLneo has been relying on several different sources of information that are all based on radically different kernel stack handling methods - it's no wonder it's so confusing! :)

@GLneo: Now that I think I understand where half of the confusion is coming from, I (and the rest of the people trying to help) will hopefully be able to give better advice. Before this can happen you'd need to choose how you want your OS to handle the kernel stack/s and let us know. Also, do you understand the consequences of each different method of kernel stack handling?

@Colonel Kernel: Coincidence? ;)


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Tue Sep 13, 2005 3:01 pm 
i think your right, i have been looking at very diferent tutorials and tried to put them togheter :P, i would like to use both a CPL=3 stack and a CPL=0 stack per task, how is THAT done?, :)


Top
  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 73 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], MichaelPetch, Octocontrabass and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group