frame and page size
frame and page size
I am considering going with a static page and frame size.
The first 32 mb will be 4kb page and frame size.
From 32 to 256 will be 2mb frame size (and 2mb page if pae is enabled, if not just 524288 4kb pages = 1 frame)
-edit- I'm swapping the order of 4 and 2 mb frames since PSE is an old extension and those systems dont have that much ram--
From 256 and up will be 4mb frame size (and 4mb page if pse is enabled, if not pse, pae with 2 pages per frame, or if not pae or pse 1048576 4kb pages = 1 frame)
My kernel will try to match allocation request in a manner that most eficiently uses these sizes:
4kb and lower request get 4kb frames,
2mb or smaller get 2mb,
and the rest get 4mb frames
If the request is for for example, 6 mb the process will receive a 4mb and a 2 mb frame mapped on its page directory/table (or other variations depending on pae and pse support)
I brainstormed about dynamic frame allocation but it seemed to complicated (complicated = a waiste of time but possible) so I choose to have a word map where each word is a process index into the process control structure list.
All of the frame, process, thread, etc control strucutres are static and there is 800 processes and threads per process and enough frames to allocate 36gb of ram. Using the larger frames means my static frame list will not take up too much memory- besides most applications will be larger than4kb or even 2mb if they contain any gui. The smaller frames will be for drivers and such. I may have to use a frame size prediction method to flag apps that use large frames to avoid giving them smaller frames that should be reserved for dma and services/drivers.
--edit- I am going with a lower number of processes and threads because when I created space to save the extra registers (mmx, fp, etc) it began to consume alot of memory--
I put a poll up top.
What do you think?
The first 32 mb will be 4kb page and frame size.
From 32 to 256 will be 2mb frame size (and 2mb page if pae is enabled, if not just 524288 4kb pages = 1 frame)
-edit- I'm swapping the order of 4 and 2 mb frames since PSE is an old extension and those systems dont have that much ram--
From 256 and up will be 4mb frame size (and 4mb page if pse is enabled, if not pse, pae with 2 pages per frame, or if not pae or pse 1048576 4kb pages = 1 frame)
My kernel will try to match allocation request in a manner that most eficiently uses these sizes:
4kb and lower request get 4kb frames,
2mb or smaller get 2mb,
and the rest get 4mb frames
If the request is for for example, 6 mb the process will receive a 4mb and a 2 mb frame mapped on its page directory/table (or other variations depending on pae and pse support)
I brainstormed about dynamic frame allocation but it seemed to complicated (complicated = a waiste of time but possible) so I choose to have a word map where each word is a process index into the process control structure list.
All of the frame, process, thread, etc control strucutres are static and there is 800 processes and threads per process and enough frames to allocate 36gb of ram. Using the larger frames means my static frame list will not take up too much memory- besides most applications will be larger than4kb or even 2mb if they contain any gui. The smaller frames will be for drivers and such. I may have to use a frame size prediction method to flag apps that use large frames to avoid giving them smaller frames that should be reserved for dma and services/drivers.
--edit- I am going with a lower number of processes and threads because when I created space to save the extra registers (mmx, fp, etc) it began to consume alot of memory--
I put a poll up top.
What do you think?
Last edited by Gizmo on Wed Aug 15, 2007 5:27 am, edited 2 times in total.
I agree with JamesM's sentiments - why use different page and frame sizes? I thought the purpose of any page frame allocator is to allocate space on a page frame.
I have gone for the 'mixed' option. My kernel and some of its basic data sits in a 4mb page, and everything else is in 4kb pages. Of course, I have a malloc() which assigns virtual RAM dynamically.
The reason for this is found in the Intel manuals. The 4MB TLB is different to the 4KB TLB. This means that my kernel's TLB entry never needs flushing, and it isn't taking up space in the 4KB TLB which can have more entries for other stuff.
Cheers,
Adam
I have gone for the 'mixed' option. My kernel and some of its basic data sits in a 4mb page, and everything else is in 4kb pages. Of course, I have a malloc() which assigns virtual RAM dynamically.
The reason for this is found in the Intel manuals. The 4MB TLB is different to the 4KB TLB. This means that my kernel's TLB entry never needs flushing, and it isn't taking up space in the 4KB TLB which can have more entries for other stuff.
Cheers,
Adam
My frames can be the same size no matter what page size the hardware its running on supports.JamesM wrote:What on earth is the advantage of having a frame size different to the page size?!
My frames are staticly sized (as said above) and have a list of words having an index to the process list or 0 for unassigned.
There is also the possibilty for switching the page extension during runtime without disrupting anything (you simply rebuild the page directories/tables) since the frames don't change (for whatever reason you want to do that).
The whole idea is that the frame sizes will be 4kb, 2mb then 4mb regardless if its running on a intel 80386 or a AMD Athlon 64 FX-74 (my next xmas present to myself ).
Besides, if it doesn't support 4mb pse then it doesn't likely have more than 32mb.
I might switch the 2 and 4mb frames since pse is a pentium extension and pae is a p6 extension, most pentium systems don't have more than 128 megs of ram.
Using larger than necessary frame sizes waiste space, but using small frame sizes waiste space for the map. Using smaller page sizes causes more misses and requires more overhead.
I'm not convinced. My frame system is merely a bitmap, the size of which is defined in architecture dependent code. Just changing a #define changes the size of all my frames (intended to correspond to page sizes). I don't see why it is any easier to use your system, in fact I would, myself, say it was harder and gives few benifits.
Just my opinion
Just my opinion
My system doesn't require being recompiled just to run on x86 systems with different page sizes. You can run the same build in long mode on a new system with 4kb and 2mb pages using the same build that runs on a 386 with 4kb pages. As long as its x86 or x86-64 my os kernel will run on it with no intervention from the user and without having to use a separate build (however you wont be able to run 64 bit apps on it if your not using x86-64 mode).
Page sizes and frame sizes match as long as the system supports the extensions- you can have both 4kb and 2mb or 4mb as long as its supported, if not then multiple pages will be used for large frames.
Using 4kb frames to support an entire 36gb address space would take about 9000000 frames x 2 bytes (process id) = 18 mb of memory to hold the frame words (set to 0 is unallocated since kernel is process 0 and doesn't use the allocation method, everything is static and small-microkernel).
Using large frame sizes drastically cuts the size of the word map to a fraction of that.
It also speeds up the allocation process since you have less frames to check on, and if you get a request you can start your free frame search at the offset for the closest frame size. I could split it up into many more sizes but if they are not 4kb, 2mb, or 4mb it will take many pages to make one frame since those are not supported page sizes.
You could probably setup PSE the easiest since all you do is place your pages directly in the directory instead of on a table and set the size bit (page directory->page).
PAE is more complicated but you need an extended version of it to enter long mode (x86 pd pointer table->page directory->page table->pages for 4kb or pd pointer table->page directory->pages for 2mb- x86-64 has a table above the pd pointer table that points to the pointer tables but still supports 4kb and 2mb).
Page sizes and frame sizes match as long as the system supports the extensions- you can have both 4kb and 2mb or 4mb as long as its supported, if not then multiple pages will be used for large frames.
Using 4kb frames to support an entire 36gb address space would take about 9000000 frames x 2 bytes (process id) = 18 mb of memory to hold the frame words (set to 0 is unallocated since kernel is process 0 and doesn't use the allocation method, everything is static and small-microkernel).
Using large frame sizes drastically cuts the size of the word map to a fraction of that.
It also speeds up the allocation process since you have less frames to check on, and if you get a request you can start your free frame search at the offset for the closest frame size. I could split it up into many more sizes but if they are not 4kb, 2mb, or 4mb it will take many pages to make one frame since those are not supported page sizes.
You could probably setup PSE the easiest since all you do is place your pages directly in the directory instead of on a table and set the size bit (page directory->page).
PAE is more complicated but you need an extended version of it to enter long mode (x86 pd pointer table->page directory->page table->pages for 4kb or pd pointer table->page directory->pages for 2mb- x86-64 has a table above the pd pointer table that points to the pointer tables but still supports 4kb and 2mb).
4kb + 2mb + dynamic. Long Mode doesn't have 4mb I believe.
What do you mean by dynamic? Dynamic page allcation maybe, thats what I got. If so then Poll needs to be redesigned and dynamic option be available for each option where mixed pages are used.
How do you do more than 4mb with the full hardware support?
Somebody who voted 'Other' must be working with different - non x86 CPU. (Was this intention of this option?)
What do you mean by dynamic? Dynamic page allcation maybe, thats what I got. If so then Poll needs to be redesigned and dynamic option be available for each option where mixed pages are used.
How do you do more than 4mb with the full hardware support?
Somebody who voted 'Other' must be working with different - non x86 CPU. (Was this intention of this option?)
A frame is not a page, pages are used to represent a frame in your page tables. You can use whatever frame size you want, its the page sizes that are dictated by hardware support.
You can support any frame size really, a frame is just a unit of allocation in physical memory that is kept track of by the kernel and given to applications to further allocate using whatever allocation method they use locally.
Whatever frame size you support is the smallest unit of allocation an application can request from the kernel.
If your frame size isn't 4kb, 2mb, or 4mb (in x86), you can use multiple pages to map each frame. If the frame size you use isn't available because the lack of extensions, just just multiple pages to map the frame.
This is not dynamic because your frame sizes don't change, you just match the request with a hardwired size the best you can (either single frame of mixed sizes that sum up to the requested size).
Dynamic means you use mixed frame sizes that are sized to fit the allocation request instead of using fixed frame sizes. This does not mean you give them a 2mb and a 4mb frame to a 6mb allocation request- you actually give them a 6mb frame.
Other means you use frame sizes other than 4kb, 2mb, or 4mb, but they are static in size (but you can have mixed sizes).
You can support any frame size really, a frame is just a unit of allocation in physical memory that is kept track of by the kernel and given to applications to further allocate using whatever allocation method they use locally.
Code: Select all
application routine calls malloc(larger_than_current_available)
malloc routine examines application maintained heap control structure and realises it needs to grow its heap.
malloc routine request a size in bytes to grow the heap from the kernel to be mapped to its local page tables
kernel searched frames, finds a free frame with size closest match to requested size
kernel mapps this frame to page table
kernel returns with size in bytes granted
malloc checks size granted, if less than requested fail
application routine uses new pointer or realizes its null and handles it
--later---
application calls free()
free marks this pointer's area as freed
free sees that this entire frame is not used and decides to free it like a good little program should
free tells the kernel to free this frame
kernel complies
free does not return anything
application keeps on trucking
If your frame size isn't 4kb, 2mb, or 4mb (in x86), you can use multiple pages to map each frame. If the frame size you use isn't available because the lack of extensions, just just multiple pages to map the frame.
This is not dynamic because your frame sizes don't change, you just match the request with a hardwired size the best you can (either single frame of mixed sizes that sum up to the requested size).
Code: Select all
page table frame table
page 1-----. .----frame 1
page 2----- | | frame 2
page 3----- | | -
page 4------| | -
page 5------+------ | ---frame 3
page 6 |------ | ----- (p2)
page 7 |------ | ----- (p3)
page 8 |------ | ----- (p4)
page 9 '------ | ----- (p5)
page 10------------' frame 4
page 11 frame 5
Pages 1-5 are mapped to frame 3.
Page 10 is mapped to frame 1.
All other frames are unallocated.
All other pages are not present (paged out or never used yet).
Dynamic means you use mixed frame sizes that are sized to fit the allocation request instead of using fixed frame sizes. This does not mean you give them a 2mb and a 4mb frame to a 6mb allocation request- you actually give them a 6mb frame.
Other means you use frame sizes other than 4kb, 2mb, or 4mb, but they are static in size (but you can have mixed sizes).
But surely, as I see it, there can only be one advantage of this:
Then there's the obvious downside, as I see it, and that is increasing the amount you swap, for no particular reason. If the MMU can handle 4k chunks, and still reach the whole of addressable memory then I would (note *I*) do everything in 4k chunks, because then if I have to swap something out of RAM, I only have to swap 4k. Swapping 2MB out is costly, whatever the medium, and IMHO doesn't make up for the decreased page directory size.
Just my thoughts...
JamesM
But, in a 36GB address space, 18mb of overhead is pretty damn negligible.Using 4kb frames to support an entire 36gb address space would take about 9000000 frames x 2 bytes (process id) = 18 mb of memory ... *snip* ...using large frame sizes drastically cuts the size of the word map to a fraction of that.
Then there's the obvious downside, as I see it, and that is increasing the amount you swap, for no particular reason. If the MMU can handle 4k chunks, and still reach the whole of addressable memory then I would (note *I*) do everything in 4k chunks, because then if I have to swap something out of RAM, I only have to swap 4k. Swapping 2MB out is costly, whatever the medium, and IMHO doesn't make up for the decreased page directory size.
Just my thoughts...
JamesM
Actually moving 2megs to and from disk is a bit faster if the task was paging in 2 megs worth of pages anyways but if you use large frames for everything then it may be an issue paging in large mostly unused frames just to read 2kb of data for example. You should put the paging in and out routines in another task and set a flag so the task switcher wont cause redundant page faults trying to run the same thread over and over again.
When you read and write to disk its best to move large peices of data since it takes time for a hard drive to find the spot where you are reading and writing this data (usually 6-10 ms for 7200rpm, 3ms for 10000 rpm) while the disk itself can read and write around 30-70 megabytes per second on the inside and 70-100mbs in the outer rings of the disk.
Also depends on your disk driver, if you handle everything first come first serve you will see a performance loss but if you handle jobs by handling those who are writing/reading to sectors close to the last read/write first using small frames won't hurt but any application waiting on paging will have a noticeable lag if its read/write sector is far from the most used sectors.
When you read and write to disk its best to move large peices of data since it takes time for a hard drive to find the spot where you are reading and writing this data (usually 6-10 ms for 7200rpm, 3ms for 10000 rpm) while the disk itself can read and write around 30-70 megabytes per second on the inside and 70-100mbs in the outer rings of the disk.
Also depends on your disk driver, if you handle everything first come first serve you will see a performance loss but if you handle jobs by handling those who are writing/reading to sectors close to the last read/write first using small frames won't hurt but any application waiting on paging will have a noticeable lag if its read/write sector is far from the most used sectors.
Gizmo, I understand how a disk driver/disk head works. I know that you get a speedup if you transfer a large chunk of contiguous data to the hard drive in one go. But.
1) The fact is if you need to swap some data out/in, you need to keep that overhead as small as possible. Therefore, it makes sense to use the smallest chunk sizes allowable by the hardware (as long as it still gives you access to the entire address space). Also, if a large swap is needed, multiple smaller chunks/pages can be amalgamated into one HDD request, to achieve the exact same speedup you get.
2) The speedup you refer to only works if the data you are writing is not just contiguous in memory, but also contiguous on the disk. If it is not, the head will thrash about, wasting time, and allowing the buffer hardware to catch up with the read/write hardware, and that large chunk you wrote at once starts turning out to be almost as inefficient as writing in smaller chunks.
So, how often do you get 2MB of contiguous data on a disk? Depending on how well defragged and how little used the device is, maybe quite often. But, as in ext2 (for example) the normal block size on a decent size HDD is 1-4KB... You are essentially hoping you manage to do a write with 250-1000 blocks contiguously. Which won't happen that often.
Don't think I'm trying to troll you, I'm not, just putting my point across
JamesM
1) The fact is if you need to swap some data out/in, you need to keep that overhead as small as possible. Therefore, it makes sense to use the smallest chunk sizes allowable by the hardware (as long as it still gives you access to the entire address space). Also, if a large swap is needed, multiple smaller chunks/pages can be amalgamated into one HDD request, to achieve the exact same speedup you get.
2) The speedup you refer to only works if the data you are writing is not just contiguous in memory, but also contiguous on the disk. If it is not, the head will thrash about, wasting time, and allowing the buffer hardware to catch up with the read/write hardware, and that large chunk you wrote at once starts turning out to be almost as inefficient as writing in smaller chunks.
So, how often do you get 2MB of contiguous data on a disk? Depending on how well defragged and how little used the device is, maybe quite often. But, as in ext2 (for example) the normal block size on a decent size HDD is 1-4KB... You are essentially hoping you manage to do a write with 250-1000 blocks contiguously. Which won't happen that often.
Don't think I'm trying to troll you, I'm not, just putting my point across
JamesM
I did throw in small frames, and they will probably be used for alot of things and most of those will be paged out.
The large frames would be used for specific large frame request, program images, shared data that cant be paged out, and large request not flagged for small frame use.
Large request may be at first small frames but if it causes alot of pf's I may bump it to a larger frame.
I may change up the ratios above of small to large to medium sized frames depending on how it all works out.
I may even change over to a mixed system that is more dynamic by allocating space for the frame map on the fly enlarging it as necessary and allowing the user of the system to set frame size preferences. (for example systems strapped for memory space would benefit from keeping the frame map as small as possible- think embedded with flash disks).
I am considering using a flag to flag a process as "existing, loaded, but in a paging in/out operation" and run a separate kernel mode task that handles the paging so the system wont thrash (the app itself will though).
Don't get me wrong, I am not highly experienced with this or anything, I just enjoy getting input from others on things I haven't mastered yet.
The large frames would be used for specific large frame request, program images, shared data that cant be paged out, and large request not flagged for small frame use.
Large request may be at first small frames but if it causes alot of pf's I may bump it to a larger frame.
I may change up the ratios above of small to large to medium sized frames depending on how it all works out.
I may even change over to a mixed system that is more dynamic by allocating space for the frame map on the fly enlarging it as necessary and allowing the user of the system to set frame size preferences. (for example systems strapped for memory space would benefit from keeping the frame map as small as possible- think embedded with flash disks).
I am considering using a flag to flag a process as "existing, loaded, but in a paging in/out operation" and run a separate kernel mode task that handles the paging so the system wont thrash (the app itself will though).
Don't get me wrong, I am not highly experienced with this or anything, I just enjoy getting input from others on things I haven't mastered yet.
I don't mind, I'd rather have someone set me strait then spend months pulling my hair out over something I overlooked or didn't understand.Don't think I'm trying to troll you, I'm not, just putting my point across Razz