Page 1 of 1
Memory Management
Posted: Thu May 25, 2006 10:14 am
by elderK
Hey all.
Ive setup a Basic Memory Manager for Citadel.
It allows me to Allocate and Free RAM.
However, There is a catch.
I can only allocate '500' blocks.
(Each block can be whatever size... but I can only allocate 500 blocks.)
Do you know a way around this?
Also, Im not in Paging mode yet.
Would it be advisable to get into Paging Mode first, then setup a Memory manager from that point on?
From what ive read, Having a Kernel loaded to 0x10000 is a BAD idea when using Paging? Yes / No?
Re:Memory Management
Posted: Thu May 25, 2006 11:09 am
by paulbarker
What sort of memory management system are you using? There are many different types and none of them have a limit on how many 'blocks' they can allocate by design. This means that your limit is probably coming from the implementation rather than any design choices.
Whether paging is necessary to implement a memory manager depends on the methods chosen. I don't know of any where paging is strictly necessary but there are a few where it would certainly help. Paging (virtual memory management) and physical memory management are completely separate things but the VMM depends on the PMM to get free pages. It is possible for the PMM to depend on the VMM but I would avoid it.
Lastly with paging you can load the kernel at any physical address and run it from a different virtual address. The virtual address space is usually split into a 'kernel' region and a 'user' region, with the kernel region at the top or the bottom but not somewhere in the middle. The exact address of the kernel within the kernel region is completely up to you. Typical splits are first 3GB for user mode and last 1GB for kernel mode, or first 1GB for kernel and last 3GB for user mode.
Re:Memory Management
Posted: Thu May 25, 2006 11:16 am
by elderK
The 500 Block limit is there by implementation.
Id like to setup paging.
However, Im unsure how to remap the Memory.
On OSDEVER.net, Ive had a look at the Basic Paging tutorial, and it sets it so that the Virtual Address = the Phsyical address. Im unsure how to make it so .. The Virtual Address is NOT the Physical address.
But say, if I want to access 0xC0000000 I will actually access 0x10000.
I want to be able to use all my memory, and I would like Memory to be Protected from external tampering.
Like, once my Kernel can execute the Servers, if a Sever gets weird and overwrites Kernel memory - It wont actually overwrite Kernel memory.
That kinda thing.
I appologize if this is a basic question and I sound like an Idiot, but... Reading some peoples documentation confuses me and my friend (who wrote the Memory MAnager for the hell of it (she was bored) set the Limitation to 500Blocks and explains things really badly, so ... I just get more confused.).
Strangely, Wikipedia explained Paging quite nicely.
For Paging, would I have to redo the GDT?
Or would the GDT I have now, be adequete?
Like, if I setup Paging - would I have to drastically modify the GDT, to point to the right places?
As of yet, the GDT is setup with a Kernel loaded at 0x10000, all I know is it jumps 0x8:0x10000 and gets to the kernel. And I know the permissions that the GDT is set with. (Base Address, Limit, etc.)
Re:Memory Management
Posted: Fri May 26, 2006 4:29 am
by paulbarker
The best thing I can suggest is to look at working kernel source code, especially projects which are designed to be easy to read and understand:
GeekOS is designed for educational use, is cleanly written and is still the basis for my GDT & IDT code. It has a set of 'projects' which tell you to add certain functionality to the basic GeekOS code and working thru these may help (I never did, so there are other ways to learn).
Minirighi is another OS that is designed to be easily understood.
Both these projects are available on sourceforge.
Another suggestion is to find a book on OS concepts, which will help you understand the differences between segmentation (the GDT does this for x86) and paging. Such concepts are highly abstract and difficult to understand from the basis of how one particular architecture (x86) deals with them. Without 'Modern Operating Systems' by Tanenbaum, I wouldn't have got much further than a protected-mode keyboard echoing program with no MM, threads or anything.
As far as you're questions, take a piece of paper and a pen. Write out the segments of your GDT, and write a few virtual addresses down. Work out how these addresses transfrom to linear addresses. Add to that a simple page map (just 8 pages will do) and work out how these linear addresses are transformed to physical addresses. Excersizes like this are the best way I know to understand how the GDT segments and paging work together and interact with one another.
This is obviously just my views, other people may have different advice.
Re:Memory Management
Posted: Fri May 26, 2006 5:23 am
by elderK
Im working on understanding Paging now.
Ive spent a good few hours reading the Intel System Developer's Documentation, the Article on GDT / IDT and paging - over and over and *over*.
Im going to get into the Implementation Stage soon. But for now, The same friend who wrote Basic Memory Management wrote a Paging System for my Kernel to use.
But, I dislike using her source.
Ive spent considerable time.. Documenting my source, tidying it.
Bug hunting.
Her code isnt documented, its horribly layed out - Statements like..
While(XXXXXX &&(XXXXXX&&(XXX))&XXX&XXX&(XX(XX&XX)))
Its scary.
And it devours thine soul.
So, ill begin writing my own Paging thing soonish.
Re:Memory Management
Posted: Sat May 27, 2006 9:22 am
by elderK
Question!
This is my 'plan' for setting up Paging System.
(Yes, thats right - The person who doesnt plan, is actually planning. *sigh*)
Alright, the first thing that bites me in the @$$ is... quite simply... We need to keep track of free RAM, for the new constructs. (That being new Pages, or new Page tables).
The Page Directory listing, will be 4kb.
I will start the Page Directory list, just after Swap.
My swap starts at 0x00020000 and 'stacks down'.
So, the Page directory will start at 0x00020001
The first Page Table, will be on Directory Zero.
But, because the Page directory is 4kb in Size,
The first page table will be located at : 0x00021001 Phsyical.
The Page table, can hold 1024 entries, so it is also 4kb in size.
So, the first Page will be located at 0x00022001.
And the page itself, holds the Address of the Physical location that this page 'maps' to (aswell as the flags).
From what ive learnt from Intel Documentation, Virtual Addresses are 'decoded' like so..
The Most significant 10 bits are are for identifying what Page Directory entry.
Second Most significant 10 bits are for identifying what Page Table entry.
The final 12 bits are for storing the Offset of the byte we are trying to access in the Page we are referring to.
So far, I think I understand it?
Anywho, I will have a Variable, that points to the next 'virgin' address of Memory, that being the next location that I know - is FREEEEE.
For example.
We have a page table at 0x00021001.
And a page, at 0x00022001.
So the next 'free' location (which we could say, place a page, or a new table)
is 0x00022005 (becuase an unsigned int is 4bytes.)
So...say.. when we go.. PageDirectory[1] = AddTable(FLAGS);
AddTable() will copy the value in the FreeAddress variable, into another Varialbe. AddTable will then 'encode' the storage variable with the Flags we wish to be set, then AddTable will return the Address to PageDirectory[1].
Of course, before returning the Address, AddTable will 'zero' the new table.
(4kb of RAM = 4byte per unsigned int * 1024) and will also increment the Free Address variable by 4kb.
So, when we go PageDirectory[1], we access a nice new chunk of memory, which will hold the start of a table.
AddPage() is done in much the same way, except for pages.
AddPage(PHSYICAL_ADDRESS_TO_POINT_TO, FLAG)
Will find place an Unsigned int at the FreeAddress, (I forget if Page table entires are encoded, ill find out shortly). Then, it will load this new unsigned int in RAM, with the Address the page maps to phsyically, then it will return the Address to the PageTable Entry.
For example:
PageDirectory[0]->PageTable[0] = AddPage(0x00000000, FLAGS);
Im not sure however, if thats how it would be written in Code.
If I add an address of a Array of unsigned int, to PageDirectory[0], how would I set ONE element of the Array, from PageDirectory?
Would I go PageDirectory[0].[0] = ? .. Im not sure.
Deallocation... would be simple, technically, pages and tables would NEVER be deallocated, however their Present bits would be revoked, so whenever you called AddTable (without going PageDirectory[x] = AddTable(..., ...)) it would just Add a new table in the 'free' slot.
I have a small question to ask, and this is one reason why ive been so feedup.
- The Processor automatically knows how to decode the Virtual Address, once we have the PDTR loaded with the correct structure, right?
Alrighty! Tell me what you think of my little idea implementation.
Thanks!