JamesM tutorial bugs? Help me with paging please!
Posted: Fri May 08, 2015 5:14 pm
Hi everyone! I'm a beginner in OS development, and as many of you I started reading osdev.org, osdever.net, Brans and JamesM tutorials, and of course this forum (and some other material out there). I am implementing physical memory management and paging, which I find a bit difficult, so I decided to read as much as I can to understand how those things work in the material mentioned before. I started reading the JamesM tutorial but then I read at osdev that It had well known bugs (http://wiki.osdev.org/James_Molloy%27s_ ... Known_Bugs). So I looked more info about that and found there was a fixed version of it here :https://code.google.com/p/jamesm-tutorials/.
Following the code and tutorials I found some things that called my attention. I wanted to ask you if it is right to say this things are bugs or it's just something I am not understanding correctly (If that is the case I would be grateful if you could explain me, please!). I've read a few times in this forum that those tutorials have some bugs left on purpose, so these might be some. If they are I think this post will be helpful for people who are struggling with errors that these may cause, or people who have missed them in a copy paste situation!
Since I am trying to implement pmm and paging I will talk about a bit of what I'm doing so you can give me your thoughts about that too.
First) The author declared arbitrary memory position for the memory manager stack in PMM_STACK_ADDR which starts at 0xFF000000. What would happen if the computer does not have that much memory if we haven't activated paging (like this case)?
In my OS I am trying that the pmm stack and paging directory are right after the kernel instead of this. I guess is just a design decision.
Anyways the problem comes here:
This is the first part of pmm.c In main.c init_pmm is called with mboot_ptr->mem_upper as parameter. With this value, he tries to find the next page aligned address and make the pmm work from there.
The thing here is:
In my OS if I print the value of mem_upper it shows me this value 0xFBC0, now for what I've seen in other examples, this value of mem_upper and the mem_lower values are used to get the total memory like this:
And for me that works great, so I don't know if I'm being lucky. But if I'm not and I'm using the mem_upper value correctly, this means that in the tutorials he is using the value in a wrong way, and starts to assign pages in that location which is below the 1Mb mark! This means that if for some reason in the paging init he asks for more pages eventually the ppm will give pages where the kernel is
Second) After pmm and vmm are initialized in main.c he tries to tell the pmm to free all the pages available like this:
I worked a bit with multiboot in my OS and found that it gives you free spaces before your kernel is loaded so you could find that from address 0x100000 to the end of memory will be free (type 1), but I know that I have loaded the kernel at 1Mb and therefore not free! (in my case mboot tells me that address from 0x100000 to 63MB is free (I am using a virtual machine with 64MB)).
So he is actually telling the pmm that the address where the kernel, page directory, page tables and pmm stack are located are free! So I beleive this is working just because since it is a stack, the first few pops give you high addresses far from the tables and the stack, but if you make a program that asks for more pages this will make the OS crash.
In my OS I use the end tag of the linker script and wherever the pmm finished the allocation of the pages asked by the vmm to calculate the real available space and then push in the stack.
Third) In the vmm.c file he does something like this a few times:
Where #define PAGE_DIR_IDX(x) ((uint32_t)x/1024)
I think it's much better if the macro does everything, something like PAGE_DIR_IDX(x) ((uint32_t)x/4096/1024)
This post is by no means trying to affirm that these are bugs (just question) and it is not meant to be a criticism of the tutorial, which I find very useful for beginners like me.
This being said I would take your responses to learn and fix my code!
Also I want to ask you something so I can keep going and make my OS better.
So far I have a physical memory manager similar to the JamesM tutorial (but changing the parts I mentioned earlier), a paging mechanism that only creates the page directory and the first page table using identity paging. Very simple.
My next goals for the OS are implementing the heap and multitasking. I know that for those things I need to use the pmm and vmm to assign the memory they need. So what should my paging and physical memory manager need to have (interface) in order to give space to the heap and every task?
Thank you very much!
You are invited to read my code and tell me what you think. Is always nice to have suggestions and if you find bugs or error would be great too!
I have spend quite a lot of time in the video driver so that it gives useful tools that can also be useful to you!
Following the code and tutorials I found some things that called my attention. I wanted to ask you if it is right to say this things are bugs or it's just something I am not understanding correctly (If that is the case I would be grateful if you could explain me, please!). I've read a few times in this forum that those tutorials have some bugs left on purpose, so these might be some. If they are I think this post will be helpful for people who are struggling with errors that these may cause, or people who have missed them in a copy paste situation!
Since I am trying to implement pmm and paging I will talk about a bit of what I'm doing so you can give me your thoughts about that too.
First) The author declared arbitrary memory position for the memory manager stack in PMM_STACK_ADDR which starts at 0xFF000000. What would happen if the computer does not have that much memory if we haven't activated paging (like this case)?
In my OS I am trying that the pmm stack and paging directory are right after the kernel instead of this. I guess is just a design decision.
Anyways the problem comes here:
Code: Select all
void init_pmm (uint32_t start)
{
// Ensure the initial page allocation location is page-aligned.
pmm_location = (start + 0x1000) & PAGE_MASK;
}
uint32_t pmm_alloc_page ()
{
if (pmm_paging_active)
{
// Quick sanity check.
if (pmm_stack_loc == PMM_STACK_ADDR)
panic ("Error:out of memory.");
// Pop off the stack.
pmm_stack_loc -= sizeof (uint32_t);
uint32_t *stack = (uint32_t*)pmm_stack_loc;
return *stack;
}
else
{
return pmm_location += 0x1000;
}
}
The thing here is:
In my OS if I print the value of mem_upper it shows me this value 0xFBC0, now for what I've seen in other examples, this value of mem_upper and the mem_lower values are used to get the total memory like this:
Code: Select all
(mboot->mem_lower + mboot->mem_upper) * 1024
Second) After pmm and vmm are initialized in main.c he tries to tell the pmm to free all the pages available like this:
Code: Select all
// Find all the usable areas of memory and inform the physical memory manager about them.
uint32_t i = mboot_ptr->mmap_addr;
while (i < mboot_ptr->mmap_addr + mboot_ptr->mmap_length)
{
mmap_entry_t *me = (mmap_entry_t*) i;
// Does this entry specify usable RAM?
if (me->type == 1)
{
uint32_t j;
// For every page in this entry, add to the free page stack.
for (j = me->base_addr_low; j < me->base_addr_low+me->length_low; j += 0x1000)
{
pmm_free_page (j);
}
}
// The multiboot specification is strange in this respect - the size member does not include "size" itself in its calculations,
// so we must add sizeof (uint32_t).
i += me->size + sizeof (uint32_t);
}
So he is actually telling the pmm that the address where the kernel, page directory, page tables and pmm stack are located are free! So I beleive this is working just because since it is a stack, the first few pops give you high addresses far from the tables and the stack, but if you make a program that asks for more pages this will make the OS crash.
In my OS I use the end tag of the linker script and wherever the pmm finished the allocation of the pages asked by the vmm to calculate the real available space and then push in the stack.
Third) In the vmm.c file he does something like this a few times:
Code: Select all
uint32_t pt_idx = PAGE_DIR_IDX((PMM_STACK_ADDR>>12);
page_directory[pt_idx] = pmm_alloc_page () | PAGE_PRESENT | PAGE_WRITE;
memset (page_tables[pt_idx*1024], 0, 0x1000);
I think it's much better if the macro does everything, something like PAGE_DIR_IDX(x) ((uint32_t)x/4096/1024)
This post is by no means trying to affirm that these are bugs (just question) and it is not meant to be a criticism of the tutorial, which I find very useful for beginners like me.
This being said I would take your responses to learn and fix my code!
Also I want to ask you something so I can keep going and make my OS better.
So far I have a physical memory manager similar to the JamesM tutorial (but changing the parts I mentioned earlier), a paging mechanism that only creates the page directory and the first page table using identity paging. Very simple.
My next goals for the OS are implementing the heap and multitasking. I know that for those things I need to use the pmm and vmm to assign the memory they need. So what should my paging and physical memory manager need to have (interface) in order to give space to the heap and every task?
Thank you very much!
You are invited to read my code and tell me what you think. Is always nice to have suggestions and if you find bugs or error would be great too!
I have spend quite a lot of time in the video driver so that it gives useful tools that can also be useful to you!