OS Development Series code question

For programming questions that do not fit in the other forums.

Moderator:Moderators

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands
Re: OS Development Series code question

Post by halofreak1990 » Tue Jul 20, 2010 7:05 pm

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:

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Tue Jul 20, 2010 7:25 pm

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.
Image

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Tue Jul 20, 2010 8:24 pm

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.

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Wed Jul 21, 2010 12:51 am

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)
Image

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Wed Jul 21, 2010 7:41 pm

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?

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Thu Jul 22, 2010 1:11 am

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.
Image

Jarvix
Posts:21
Joined:Mon Apr 06, 2009 6:08 am

Re: OS Development Series code question

Post by Jarvix » Sat Aug 07, 2010 10:59 am

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
Jinix. Kernel programming is a black art that should be avoided if at all possible.

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Sat Aug 07, 2010 1:07 pm

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?

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Sat Aug 07, 2010 1:20 pm

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.
Image

Jarvix
Posts:21
Joined:Mon Apr 06, 2009 6:08 am

Re: OS Development Series code question

Post by Jarvix » Sat Aug 07, 2010 2:08 pm

Are you going to put the kernelstack below 3GB?!??!?

// Jarvix
Jinix. Kernel programming is a black art that should be avoided if at all possible.

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Sat Aug 07, 2010 8:17 pm

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.

Jarvix
Posts:21
Joined:Mon Apr 06, 2009 6:08 am

Re: OS Development Series code question

Post by Jarvix » Sun Aug 08, 2010 7:13 pm

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
Jinix. Kernel programming is a black art that should be avoided if at all possible.

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Mon Aug 09, 2010 10:21 pm

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.

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: OS Development Series code question

Post by Andyhhp » Mon Aug 09, 2010 10:31 pm

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
Image

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: OS Development Series code question

Post by halofreak1990 » Tue Aug 10, 2010 6:55 pm

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.

Post Reply