Page 2 of 3

Re: OS Development Series code question

Posted: Tue Jul 20, 2010 7:05 pm
by halofreak1990
I assume this is the code (in the 2nd stage bootloader) I'm supposed to modify?

Code: Select all

   mov      ax, 0x0000         ; stack begins at 0x9000-0xffff
   mov      ss, ax
   mov      sp, 0xFFFF

A little calculation tells me I currently have a 27K stack?
0xffff = 63K
0x9000 = 36K
63 - 36 = 27K

I guess if I'd change it to get a 128K stack, I'd be better off. Though I'm not sure whether to keep the stack right below the DMA buffer, which if I'm correct, resides at 0x10000, which would indeed mean I'm overflowing... into the DMA buffer :shock:

Re: OS Development Series code question

Posted: Tue Jul 20, 2010 7:25 pm
by Andyhhp
tbh, the setup routine for your kernel should map the stack to the 3GB mark in memory or something.

Thats what happens in most modern operating systems.

Re: OS Development Series code question

Posted: Tue Jul 20, 2010 8:24 pm
by halofreak1990
Andyhhp wrote:tbh, the setup routine for your kernel should map the stack to the 3GB mark in memory or something.

Thats what happens in most modern operating systems.

That means the kernel will have to move... it's currently located at 3GB virtual. Would you happen to know where most OSs map their kernel?
Also, I'm wondering if it's better to place the kernel somewhere else than at 12K (0x3000) in real mode.

Re: OS Development Series code question

Posted: Wed Jul 21, 2010 12:51 am
by Andyhhp
The stack grows downward.

If you start it at 4 bytes below the 3GB mark then it will not interfear with the kernel. (subject to buffer overflows etc but usermode applications are safe from that when properly set up)

Re: OS Development Series code question

Posted: Wed Jul 21, 2010 7:41 pm
by halofreak1990
The bootloader sets up an initial stack for the kernel to use, but I'm free to have the kernel create itself a new one anywhere I want, right?
Also, do I have to clear the old one, or could I just set the registers to point to the new stack location?

Re: OS Development Series code question

Posted: Thu Jul 22, 2010 1:11 am
by Andyhhp
You are perfectly free to move your stack anywhere you want at any time you want.

However, if you move the stack, you are essentially creating a new one, meaning that you are currently at the top of the stack. Trying to pop items beyond the top of the stack is going to result in garbage, so you can only safely move the stack from a function which will never return (i.e. your kernel loading routine which calls kmain then loops forever)

As for the old stack, it really doesnt matter what you do with it. Leave it along and at some point in the future, its page will be allocated and the data will be written over.

Re: OS Development Series code question

Posted: Sat Aug 07, 2010 10:59 am
by Jarvix
if you 'move' the stack, so you just want it to be at another address (eg 0xE0000000 insetad of at 1MB), you wil need to determine top of the stack, copy all to the new address (top->current esp == to ==> 0xE0000000->(top-current esp+0xE0000000). That piece of math is calculating end of new stack using current stacks size ;)

Then you will need to find all stored EBPs and change them. If you do not do this, no function can get its stack back, ESP will be corrupted, and boom! Finding and chanhing ESPs is tricky. You could do this: walk through the stack, if the data on it is an address between top and bottom of the old stack, change it to new address:

Code: Select all

// walk trough stack:
uint32_t *stack = oldTop;
while((uint32_t)stack > oldBottom)
{
   // *stack contains data
   if(*stack > oldBottom && *stack <= oldTop) // If points to stack
   {
        *stack = (*stack-oldBottom)+newBottom; // old address minus old bottom makes offset on stack (real addressing, no stack wise ;)). Then add new bottom, which then is new address.
    }
   stack--; // GCC will take 4 bytes off since its 4byte pointer
}


That would work. Try to use as much as ASM as possible, since THEN you have control over the stack (push, pop). GCC will use stack for loops too, so be warned:!: For copying stack use plain asm.

Good luck!

// Jarvix

Re: OS Development Series code question

Posted: Sat Aug 07, 2010 1:07 pm
by halofreak1990
0xC0000000 is 3 GB, so the new stack would be at 0xBFFFFFFB (3GB - 4 bytes, growing downwards.)

I'm going to relocate the stack before the kernel uses anything of it, so I only need to adjust the stack pointers.
So, all I have to do is

Code: Select all

mov esp, BFFFFFFBh 
and I'm done, or do I need to set ss to some value also?

Re: OS Development Series code question

Posted: Sat Aug 07, 2010 1:20 pm
by Andyhhp
typically, ss has the same selector as ds, es, fs and gs. All that matters for your kernel is that ss is a descriptor which allows you to access all of memory.

Re: OS Development Series code question

Posted: Sat Aug 07, 2010 2:08 pm
by Jarvix
Are you going to put the kernelstack below 3GB?!??!?

// Jarvix

Re: OS Development Series code question

Posted: Sat Aug 07, 2010 8:17 pm
by halofreak1990
Jarvix wrote:Are you going to put the kernelstack below 3GB?!??!?

Sure, why not? The stack grows downwards, away from the kernel, which resides at 3GB.

Re: OS Development Series code question

Posted: Sun Aug 08, 2010 7:13 pm
by Jarvix
i would put the userstack there

the kernelstack is fixed size, every process has one, its used only to switch rpocesses, and some interrupt handling. They wont be big.

You also need to be able to access any other kernel stack from process A
when switching processes
so you need them to be above 3GB all on other address

:)

Thats why

// Jarvix

Re: OS Development Series code question

Posted: Mon Aug 09, 2010 10:21 pm
by halofreak1990
Just a question... Does your homebrew kernel run on real hardware without problems?
I can't for the life of me figure out why the floppy reading is so god damned buggy outside VirtualPC, because its keeping me from continuing on other aspects of the kernel.

Also,

Code: Select all

mov esp, somevalue
should adjust the stack pointer, right? I do this as the very first thing in my kernel initialization, and it triple faults.

Re: OS Development Series code question

Posted: Mon Aug 09, 2010 10:31 pm
by Andyhhp
That will move the stack pointer.

However, make sure that you disable interupts whilst doing so otherwise the pipeline creates a state where you dont actually have a valid stack.

Also, ensure that the address you are moving to is readable and writeable by the kernel (at the least) and if you have enabled paging, ensure that you are in a page which is present. (Else you get the Page Fault handler trying to use a stack on a page which is not present, which causes a GPF)

~Andrew

Re: OS Development Series code question

Posted: Tue Aug 10, 2010 6:55 pm
by halofreak1990
In inserted the

Code: Select all

mov esp, 0xBFFFFFFB
into the asm block before the kernel entry, right after the cli command.
I guess my problem lies in the paging. It's enabled before the kernel is loaded, and I'm not dealing with it atm.

Also, I noticed the kernel is loaded at RealMode address 0x3000, and the stack at 0x9000.
Now, a bit of calculating tells me there's roughly 24 KB between those two points in memory.
You told me the stack grows downwards... which means that, with my kernel being 22-23 KB in size, there's about 1KB for the stack before I start running into the kernel's back-end.