Page 1 of 1

kernel stack location

Posted: Wed Oct 26, 2011 5:40 pm
by dawix
Hi,
i have my kernel loaded at 0xC0000000, when my kernel starts it uses a temporary stack in the bss section of 4096 bytes, it then enters in protected mode starting using the user mode stack at 0xBFFF0000, when it forks for the first:
all the kernel code pages are linked
all the user mode pages (under 0xC0000000) are copied in new frames.
Everithing works but...what about the kernel stack i don't want a shared one i want that every process have his kernel stack (it's correct?! )
So where to put the kernel stack?! i have to copy the content of the temporary one in a new frame before the fork so that when a fork happens all the processes have the same virtual stack address? because if i don't copy it before the first fork the first forked process must be treated in a different way than the 2nd , 3rd, etc forked tasks.
I don't know if it's clear but if it's not the kernel of the question is: TELL ME ABOUT THE KERNEL STACK :D

Re: kernel stack location

Posted: Wed Oct 26, 2011 5:50 pm
by AndrewBuckley
your trying to give user processes the kernel stack? why?

Re: kernel stack location

Posted: Wed Oct 26, 2011 6:24 pm
by dawix
no...every process has it's own global table directory. This directory maps:
0x00000000:0xBFFFFFFFF -> user space
0xC0000000:0xFFFFFFFFF -> kernel space
in the directory all the kernel space pages are linked to the first process kernel code, all the rest is copied. Now i want to copy the kernel stack as well so every process can do a syscall using the shared code and heap but using it's own copied kernel stack.
I heard the every task must mantain a user stack and a kernel stack.

Re: kernel stack location

Posted: Thu Oct 27, 2011 4:19 am
by egos
You can map all kernel stacks into kernel space or remap each stack at same address when task switching occurs. I use first variant because I store thread structure in the stack region.

Re: kernel stack location

Posted: Thu Oct 27, 2011 8:08 am
by dawix
Ok you map the kernel stack in the kernel space but...when you fork a new process. you don' link the father kernel stack right? you copy it so the child process just have linked (in it's page directory/table) the kernel code and heap? for the new kernel stack you allocate a new frame and copy in it the original one content!? tell me if i'm wrong...
thanks

Re: kernel stack location

Posted: Thu Oct 27, 2011 9:28 am
by egos
When I create starting application thread I just allocate a new stack frame, map memory into it, write start stack frame and thread structure to the top, write executable file name and parameter string to the bottom, insert thread in the run queue. After thread will take control the InitFirstUserThread routine will be executed.

Re: kernel stack location

Posted: Thu Oct 27, 2011 7:44 pm
by dawix
ok i solved in this way, maybe it's the linux way because i saw in the linux kernel internals book that is implemented like this:
every process have his kernel stack... the kernel mantains a series of task struct associated with the kernel stack that the process use, like this:

Code: Select all

 
union {
    task_t task;
    uint kstack[1024];
} init_task;
for every context switch i update the unique tss with the current process kstack address so when is in user mode and an interrupt happens it start using it's kernel stack. In this way is possible to have nested interrupts and a preemptive kernel.
Thanks God :D

Re: kernel stack location

Posted: Thu Oct 27, 2011 8:07 pm
by dawix
ah the tss is updated in this way:

Code: Select all

current_task = current_task->next;
tss[1] = current_task->stacktop;                   // the ESP0 field in the tss is updated with a correct value
the stacktop value is assigned for the 1st process statically as:

Code: Select all

union {
    task_t task;
    uint kstack[1024]
} start_task;
...
....
start_task->stacktop = &start_task[1024]
for the other tasks in the fork function like this:

Code: Select all

task_t *newtask = (task_t *) malloc(4096);
newtask->stacktop = ((uint)newtask +4096);
newtask->eip = ret_from_syscall;
newtask->esp = newtask->stacktop  - (14*4); // minus all the values pushed in the stack by the "syscall" asm routine before calling the "syscall_handler" and by "int 0x80" automatically, so that returning in "ret_from_syscall" pops the values correcly )
memcopy(newtask + sizeof(task_t), current + sizeof(task_t), 4096-sizeof(task_t))    // this copies the values in the stack used by "ret_from_syscall"
and this is the syscall asm part

Code: Select all

syscall:
    pusha                    ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

    mov ecx, ds               ; Lower 16-bits of eax = ds.
    push ecx                 ; save the data segment descriptor

    mov cx, 0x10  ; load the kernel data segment descriptor
    mov ds, cx
    mov es, cx
    mov fs, cx
    mov gs, cx

    call syscall_handler          ; where the syscall is dispatched depending on eax value
ret_from_isr:
    pop ebx        ; reload the original data segment descriptor
    mov ds, bx
    mov es, bx
    mov fs, bx
    mov gs, bx

    popa           ; Pops edi,esi,ebp...
    iret              ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
so actually the ony things that the current process must copy in the new process stack is the value popped in ebx, the values popped by popa and the stuff used by iret to return in usermode [-o<