Page 1 of 1
Setting ESP right when creating task
Posted: Wed Jul 10, 2013 5:23 am
by max
Hey guys!
Its been quite a few months since ive been posting here, but ive finally found time for OS development again. <3
Well, I have a little problem when it comes to setting the initial ESP when creating a task. I simply want to create a kernel task with the stack im allocating with my MemoryAllocator.
When it comes to setting the right ESP i cant really figure out what to set here.. the process->stackAddress is the low end of my stack coming from the allocator and MEMDEF_PROCESS_STACKSIZE defines the size to use (0x4000 here). What do I have to set here to make sure the process can run correctly?? Does a stack have to be somehow aligned or something?
Code: Select all
Process* process = (Process*) MemoryAllocator::allocate(sizeof(Process));
process->stackAddress = (unsigned int) (MemoryAllocator::allocate(MEMDEF_PROCESS_STACKSIZE));
unsigned int esp = (process->stackAddress + MEMDEF_PROCESS_STACKSIZE); // Problem
Registers* cpuState = (Registers*) MemoryAllocator::allocate(sizeof(Registers));
cpuState->eax = 0;
cpuState->ebx = 0;
cpuState->ecx = 0;
cpuState->edx = 0;
cpuState->esi = 0;
cpuState->edi = 0;
cpuState->ebp = 0;
cpuState->esp = esp;
cpuState->eip = (unsigned int) method;
cpuState->cs = 0x18 | 0x03;
cpuState->ss = 0x20 | 0x03;
cpuState->eflags = 0x202;
process->id = nextProcessId++;
process->alive = true;
process->cpuState = cpuState;
if (first == 0) {
process->next = process;
process->previous = process;
first = process;
last = process;
} else {
last->next = process;
process->previous = last;
last = process;
process->next = first;
first->previous = last;
}
Thank you very much!
Greets, Max
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 5:37 am
by AJ
Hi,
If I understand your code correctly, you seem to be allocating a stack for a ring 3 process within your kernel heap. Is that correct? I would imagine that your problem is a PFE as soon as you iret.
You also seem to allocate the processes initial ring 0 stack (the stack containing the initial register values etc...) to the exact size of the registers you need. This means that as soon as your ring 3 process gets interrupted, you are using a stack which will start overwriting kernel heap values as soon as you make a function call.
What are the symptoms you get when you have tried to run your ring 3 task?
Cheers,
Adam
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 5:42 am
by max
Thanks for the quick reply.
Actually im not trying to create a Ring 3 process but a Ring 0/kernel process with kernel heap. The constant im using there (MEMDEF...) contains the value 0x4000, not the size of the process register struct.
The symptoms i get is that the os completely freezes up, so i guess values of the process struct are overwritten and the scheduler does not work correctly anymore..
EDIT: Oh.. i guess ive set the CS and SS registers wrong, those are the values for a Ring 3 process am i right? Is there an explanation what values to use here? Thanks in advance!
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 5:59 am
by AJ
Hi,
Yes - you need to check the Intel manuals for the DPL - the lower bits of the segment selectors.
I'm aware what the constant contains, but as it stands, you are setting up *2* stacks for a ring 3 task. The first stack is defined by esp and will be what the process uses when it runs. The second stack is defined by cpuState and contains your registers that will be loaded when you switch stacks to load up the new task.
For a ring 0 task, you do not need this "complexity" and you can just stick the values straight in to the same ring 0 stack that your initial register values are loaded on. You'd be better to plan ahead where you are going to put your process stacks in linear memory and allocate appropriately there.
Cheers,
Adam
[Edit: If you are copy and pasting this code from a tutorial, it may be better to take a step backwards and think about what is actually happening in the CPU when you switch stacks. This will help you plan for where you actually want to allocate that memory. To your previous question, yes, you will definitely want the stacks page aligned so that you can also allocate guard pages and assign privilieges appropriately.]
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 6:08 am
by Kevin
max wrote:When it comes to setting the right ESP i cant really figure out what to set here.. the process->stackAddress is the low end of my stack coming from the allocator and MEMDEF_PROCESS_STACKSIZE defines the size to use (0x4000 here). What do I have to set here to make sure the process can run correctly?? Does a stack have to be somehow aligned or something?
No, it doesn't have to, though word-alignment is probably advisable. I guess that you allocate a new page anyway, so that's good enough alignment-wise. Your esp looks fine either way.
Code: Select all
process->stackAddress = (unsigned int) (MemoryAllocator::allocate(MEMDEF_PROCESS_STACKSIZE));
unsigned int esp = (process->stackAddress + MEMDEF_PROCESS_STACKSIZE); // Problem
Not related to your problem, but uintptr_t instead of unsigned int would make the code more portable.
Code: Select all
cpuState->cs = 0x18 | 0x03;
cpuState->ss = 0x20 | 0x03;
These are indeed ring 3 descriptors. I suspect that the correct values are 0x8 and 0x10, though I don't know your GDT.
Where do you do the actual stack switching?
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 6:18 am
by max
No, i did not copypaste this code, but ive been out of this topic for a while and have to work into my own sources quite a bit ^^
@AJ Where do you see the setup of 2 stacks in the code? Initially, i have a small kernel stack which is used for setting up everything and then creating the first real process (i only need ring0-tasks currently). The process then gets its own 16kib stack allocated and gets added to the process list. Then i enable scheduling and create further processes. On process switching i store the register values on the current process's stack and load the next processes registers from the next stack
@Kevin my problem were actually the segment register values ive set there.. the actual task switching is done in my interrupt handler.
zusätzlich sollten du und ich mal wieder schreiben, add mich mal in facebook, kriegst ne pn ^_^
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 6:37 am
by Kevin
max wrote:On process switching i store the register values on the current process's stack and load the next processes registers from the next stack
Then what is cpuState? Assuming your MemoryAllocator::allocate() isn't doing "interesting" things, it's not on any stack.
zusätzlich sollten du und ich mal wieder schreiben
Jawohl.
Re: Setting ESP right when creating task
Posted: Wed Jul 10, 2013 7:21 am
by AJ
Hi,
max wrote:@AJ Where do you see the setup of 2 stacks in the code?
max wrote:
Initially, i have a small kernel stack which is used for setting up everything
...
The process then gets its own 16kib stack allocated.
But why are you allocating any stacks in the kernel heap? Surely that's asking for heap data to be overwritten as soon as anything overflows. It would be much cleaner and easier to debug if you had a stack area with suitable guard pages so that you would instantly know in a debugger what has gone wrong with locations of ESP etc... I'm getting the feeling that some more work needs doing on the infrastructure / design before the OS should be running multiple tasks.
What is actually going wrong here? What CPU exception(s) occur etc...? How about the actual assembly code that switches in the new task - is everything being loaded from the stack properly?
Cheers,
Adam
Re: Setting ESP right when creating task
Posted: Thu Jul 11, 2013 2:50 am
by max
Im allocating the stacks in the kernel heap because I only need processes running in kernel space at the moment. Im planning to implement guard pages, too.
The switching works properly now, as I said the segment registers were set to ring 3 values
Thanks for your help!