Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
With the conception I presently have, kernel addresses always have the same logical mapping regardless of what process is running. I just can't see any other way to perform task switching. I mean, when you switch a process, the kernel components still reside at the same logical addresses.
Assuming this is the proper way to do things, say I want the upper 2GB of the logical memory space (on x86) to be the kernel's memory space. Half of the page directory should really be shared with all other processes. However, this would mean that any time I change a kernel-region page directory entry , I will have to update all processes' page directories (or lazily do it as I task switch in to them). Is there a better way?
On a slightly unrelated note, I would like to be using my own data structure for page table entries. Is there a better or more portable (the latter tends to result in cleaner code IMHO, so I am very interested) to handle this effectively than essentially emulating the page directory/page table system? I'm aware not all platforms use two layers for paging, hence the question.
you don't need to update all the process pagetables if you have 2-levels paging: just make the page directory entries that correspond to kernel pages point to the *same* page frames (which means that kernel page tables will also be shared by all processes). Modifying the kernel page table content will reflect in every process immediately.
Zer wrote:However, this would mean that any time I change a kernel-region page directory entry , I will have to update all processes' page directories (or lazily do it as I task switch in to them). Is there a better way?
Remember you only need to update all process' page directories when a kernel page directory entry changes, i.e. the first time you make a mapping in a particular 4MB region or when you unmap everything. I handle this by looking for page faults in the kernel half of the address space and keeping a master copy of the kernel page directory.
On a slightly unrelated note, I would like to be using my own data structure for page table entries. Is there a better or more portable (the latter tends to result in cleaner code IMHO, so I am very interested) to handle this effectively than essentially emulating the page directory/page table system? I'm aware not all platforms use two layers for paging, hence the question.
Why do you need your own page table format? You'll still need to use actual page directories/tables in the end. I would make it more abstract and keep track of blocks of virtual address space; leave the page table handling to the architecture-specific parts of the kernel.
Why do you need your own page table format? You'll still need to use actual page directories/tables in the end. I would make it more abstract and keep track of blocks of virtual address space; leave the page table handling to the architecture-specific parts of the kernel.
I'd like to be able to map multiple processes' logical pages to the same physical addresses, for a Copy-on-Write scheme, among other things. So the structure for a page will be a linked list of different logical mappings. I can't store this extra information in a normal page table entry, so I need my own format. I didn't mean handling the interface with the hardware -- just the abstraction above the physical page tables.
All i see you'll need for copy-on-write is a field counting how much references are made to a given physical page (one byte for every 4K of your memory: it'll just consume about 0.4% of your actual memory size and can even be reduced if you consider that only a sub-range of your physical memory is sharable with copy-on-write).
if (!page.write && !page.copy_on_write) write_fault_report(page);
if (!page.write && page.copy_on_write && !morecopies[page])
page.write=true // you were the last user of the page :)
if (!page.write && page.copy_on_write && morecopies[page]) {
PageFrame frame=alloc_new_page_frame();
physical_memcpy(frame,page.frame);
synchronized(morecopies) { morecopies[page]--; }
page.frame=frame; page.write=true;
page.copy_on_write=false;
flush_TLB_cache(page.linear_address);
}
When you release a page which has "copy_on_write" bit set, you'll decrement morecopies[page] or free the frame if !morecopies[page]
Does it make sense ? i don't see the need for another table around here ...