Page 4 of 6

Re:tss and user space

Posted: Tue Jan 03, 2006 9:56 am
by JAAman
Brendan wrote: Once the initial TSS is setup, you'd just change "TSS->esp0" during every task switch (if each task has it's own kernel stack).
this is not necessary, the kernel stack should not be in shared space, and should start at the same point for each task, therefore, esp0 doesn't ever need to change (unless for some reason your storing values on the stack between calls?)

on task switch, the kernel stack is swaped when the address space is swapped, and when the kernel function ends, it returns to its entry point (at the start of task), the only time this won't be correct on task swap, is if that task is in a kernel routine, in which case it will return to start before esp0 is ever used

basically, once it is set up, the TSS will never need to be changed, unless you are using the I/O bitmap

Re:tss and user space

Posted: Tue Jan 03, 2006 11:24 am
by Colonel Kernel
JAAman wrote: this is not necessary, the kernel stack should not be in shared space, and should start at the same point for each task, therefore, esp0 doesn't ever need to change (unless for some reason your storing values on the stack between calls?)
Do you mean you'd have multiple kernel stacks in physical memory, but map the "current" one into a fixed location in the kernel's address space, or do you mean having only one kernel stack per processor? If it's the latter, you may find making the kernel itself preemptable to be a bit of a challenge...
on task switch, the kernel stack is swaped when the address space is swapped, and when the kernel function ends, it returns to its entry point (at the start of task)
What if not every task switch results in an address space switch (e.g. -- switching between threads in the same process)?

Re:tss and user space

Posted: Tue Jan 03, 2006 3:29 pm
by Assembler
Kemp wrote: Pointers use ->
Simple (and not so simple) variables use .

So you would use .
Hi,

"->" is used when u got a pointer to the structure
so "p->whatever" equals "(*p).whatever" because the "." is higher than "*".
but if u have the structure not a pointer to it u should use the "." normally.

thanks

Re:tss and user space

Posted: Tue Jan 03, 2006 4:31 pm
by Kemp
Which is exactly what I said, only worded more complicated...

Re:tss and user space

Posted: Tue Jan 03, 2006 4:47 pm
by Assembler
oh, i know that's what u said but i just wanted to make it more clearer for him.

Re:tss and user space

Posted: Tue Jan 03, 2006 6:09 pm
by Kemp
so "p->whatever" equals "(*p).whatever" because the "." is higher than "*"
To be fair, that was something I didn't mention (though I didn't go into pointer details).

A * before a pointer name dereferences the pointer (giving you the variable, or more accurately the memory location, it is pointing at). So for instance:

Code: Select all

char foo = 'A';
char *pChar = foo;
Would create a variable called foo that contains a char and a pointer called pChar that points to this variable.

Code: Select all

(*pChar) = 'B';
Would set the variable that pChar points to (foo) to 'B'.

Conversely, an & before the variable name gives the address of the variable (essentially creating a pointer on the fly), in this case

Code: Select all

&foo
would give you a pointer to foo.

Re:tss and user space

Posted: Tue Jan 03, 2006 6:57 pm
by Colonel Kernel
Kemp wrote:

Code: Select all

char foo = 'A';
char *pChar = foo;
I see a bogon. Did you mean this?

Code: Select all

char foo = 'A';
char *pChar = &foo;

Re:tss and user space

Posted: Tue Jan 03, 2006 7:18 pm
by kataklinger
Probably he wanted to write the secon one, first one won't even compile and has no sense :)

Re:tss and user space

Posted: Wed Jan 04, 2006 7:14 am
by Kemp
Yeah, sorry about that one, of course I meant &foo :P

Re:tss and user space

Posted: Wed Jan 04, 2006 9:23 am
by JAAman
@colonel kernel

the former, for each task, the kernel stack is mapped to the same place

for thread switches, some of the address space should be switched anyway (imho), however, if you didn't want to do any switching, you could change SS:ESP0 only for thread switches, but not task switches (you have to handle them differently anyway, just change SS:ESP0 instead of CR3 for a thread switch)

really haven't desided how to handle threads yet myself, still thinking about a few things, but i will be changing at least part of the address space, prob including the kernel stack

Re:tss and user space

Posted: Wed Jan 04, 2006 9:29 am
by kataklinger
But address space switching is expensive operations, and I think that's way they call threads light-weight processes, because you they don't have separate address space

Re:tss and user space

Posted: Wed Jan 04, 2006 9:40 am
by JAAman
no, full address space switching is expensive, you can also switch only a few pages (the kernel stack, processID, etc) in fact i believe this is quite common way to handle it -- iirc many systems do this with the primary stack as well

switching pages is expensive, however it is also quite possible to implement threads as completely separate processes also (which i have actually considered myself, but i might not) just COW everything and you have a separate thread in a separate process, which actually makes a lot of sence from a security point (protecting threads from each other)

Re:tss and user space

Posted: Wed Jan 04, 2006 11:26 am
by GLneo
ok i know i have a bad limit but how do i change that???, here some code if it helps:

Code: Select all

stack_data_t *schedule(stack_data_t *regs)
{
    cur_task_time_equ(get_pri_time(cur_task_pri()));
    rrq[front].stack = regs;
    front_to_end();
    TSS.esp0 = (int)rrq[front].stack;
    return (stack_data_t *)TSS.esp0;
}

stack_data_t *task_timer_c(stack_data_t *regs)
{
    clock();
//    (void)inport(0x60);
    outport(0x20, 0x20);
    if(cur_task_time() > 0)
    {
        dec_cur_task_time();
        return regs;
    }
    else
        return schedule(regs);
}

void make_task(int pri, char *name, void (*entry)(), int ring)
{
    void *stack_mem;
    stack_data_t *stack;

    stack_mem = (unsigned int *)malloc(STACK_SIZE);
    stack_mem += STACK_SIZE - sizeof(stack_data_t);
    stack = stack_mem;
    if(ring == 0)
    {
        stack->gs = KERNEL_DATA_SEG;
        stack->fs = KERNEL_DATA_SEG;
        stack->es = KERNEL_DATA_SEG;
        stack->ds = KERNEL_DATA_SEG;
        stack->cs = KERNEL_CODE_SEG;
    }
    else
    {
        stack->gs = USER_DATA_SEG;
        stack->fs = USER_DATA_SEG;
        stack->es = USER_DATA_SEG;
        stack->ds = USER_DATA_SEG;
        stack->cs = USER_CODE_SEG;
    }    
    stack->edi = 0;
    stack->esi = 0;
    stack->esp = (unsigned int)stack;
    stack->ebp = stack->esp;
    stack->ebx = 0;
    stack->edx = 0;
    stack->ecx = 0;
    stack->eax = 0;
    stack->eip = (unsigned int)entry;
    stack->eflags = 0x00000202;
    
    strncpy(rrq[end].name, name, 32);
    rrq[end].stack = stack;
    rrq[end].ss = KERNEL_STACK_SEG;
    rrq[end].priority = pri;
    rrq[end].time = get_pri_time(pri);
    end++;
}

void fill_tss()
{
    TSS.ss0 = 0x10;
    TSS.bitmap = 0xFFFF;
}    

void start_sys()
{
    make_task(3, "KERNEL", task0, 0);
    make_task(3, "task0", task0, 3);
    make_task(3, "task1", task1, 3);
    fill_tss(); // fil the struct
    set_a_gdt(5, (unsigned long)&TSS, sizeof(TSS), 0x89, 0xCF); // put a pointer in GDT
    setup_tss(); // put pointer to GDT entery in cpu
    set_a_idt(32, (unsigned)task_timer, 0x08, 0x8E); // redirect timer
}
see anything???, thx

p.s. i know what -> and . do, i just couldn't remember which was which :)

Re:tss and user space

Posted: Wed Jan 04, 2006 12:07 pm
by kataklinger
Wrong part of code.

Send code for: set_a_gdt() & where do you load GDTR.

Re:tss and user space

Posted: Wed Jan 04, 2006 2:05 pm
by Colonel Kernel
JAAman wrote: no, full address space switching is expensive, you can also switch only a few pages (the kernel stack, processID, etc) in fact i believe this is quite common way to handle it -- iirc many systems do this with the primary stack as well
By "primary stack", you mean user-mode stack, right? Which OSes that support multi-threading have every user-mode stack at the same virtual address...?

The only case I know of where a thread has its own private pages would be thread-local storage. You can wrap access to thread-local storage behind a few system calls, which means you wouldn't have to switch those pages if the calls were never made. IMO it doesn't make sense to flip pages on every thread switch -- this negates some of the performance benefit of multithreading.
switching pages is expensive, however it is also quite possible to implement threads as completely separate processes also (which i have actually considered myself, but i might not) just COW everything and you have a separate thread in a separate process, which actually makes a lot of sence from a security point (protecting threads from each other)
You're describing classic UNIX processes and fork(). This is not the same as multi-threading, which by definition involves supporting multiple threads per address space. Forked processes do not really share any address space since a write to memory by one process will not be visible to the other process.