Hi! I've been trying to write an x86 OS based off the template provided by the CMU OS course[http://www.cs.cmu.edu/~410/] (I'm attending the school but won't be able to take the course, at least not for a few years maybe). It's a basic OS with paging-based VM, software kernel threads (only one TSS), some basic linux-style syscalls, and console/keyboard drivers.
It's been going well (I've got single-threaded programs to run =) ) but I'm a bit stuck on forking. Most of the resources I've seen deal with the memory 'cloning' by either COW (which I really don't want to do yet) or by disabling paging temporarily to copy from one physical space to another. What I was thinking was to take an alternative route: have a page of kernel memory set aside to act as a sort of 'fake buffer' for copying memory.
When I initialize paging, I set aside a page of kernel memory, then, when I need to do what would normally be just a memcpy, I go page by page and first set the page table entry corresponding to the fake buffer to be equal to that of the destination (in another PD than the current one). That way there is now a mapping in the current PD that points to the physical memory where I want the data to end up. I copy it in and repeat. At the end I just zero the fake buffer page entry for use later.
I've not seen this sort of approach anywhere, and can't get it to work. Is there something fundamental that I'm missing that does not allow this to work?
Thank you very much, I hope I can learn a lot from all of you =)
Copying memory for fork across page directories
Re: Copying memory for fork across page directories
Crash, memory corruption, or nothing happening at all?QueueTsar wrote:...can't get it to work.
Every good solution is obvious once you've found it.
Re: Copying memory for fork across page directories
Sorry, I guess I overlooked that since I was focusing more on if there was a 'theory' reason why it won't work. Otherwise I assume it's just an error somewhere. I end up page faulting on the first instruction of the new process. When copying over the memory, the first page copies fine, but then the next page copies to the same place as the first one. As the rest copy, some go to the proper place and some go to a previous location. It seems like the page table changes simply aren't 'sticking'. If I flush the tlb (by 'touching' cr3) before each memory write to the 'fake buffer' then it works fine but that almost entirely defeats the purpose of this method.Solar wrote:Crash, memory corruption, or nothing happening at all?QueueTsar wrote:...can't get it to work.
Is the overall idea unsound? Is there a way to force a page to stay out of the tlb?
Re: Copying memory for fork across page directories
I don't understand what you are trying to achieve here, nor what you are actually doing. Can you perhaps elaborate or rephrase a bit?QueueTsar wrote:When I initialize paging, I set aside a page of kernel memory, then, when I need to do what would normally be just a memcpy, I go page by page and first set the page table entry corresponding to the fake buffer to be equal to that of the destination (in another PD than the current one). That way there is now a mapping in the current PD that points to the physical memory where I want the data to end up. I copy it in and repeat. At the end I just zero the fake buffer page entry for use later.
JAL
Re: Copying memory for fork across page directories
You have to flush the TLB every time you change something in page tables. That would result in a really poor performance stuff so instead of that you should use the INVLPG instruction to invalidate only the changed entry in the TLB and then it should work.QueueTsar wrote:Sorry, I guess I overlooked that since I was focusing more on if there was a 'theory' reason why it won't work. Otherwise I assume it's just an error somewhere. I end up page faulting on the first instruction of the new process. When copying over the memory, the first page copies fine, but then the next page copies to the same place as the first one. As the rest copy, some go to the proper place and some go to a previous location. It seems like the page table changes simply aren't 'sticking'. If I flush the tlb (by 'touching' cr3) before each memory write to the 'fake buffer' then it works fine but that almost entirely defeats the purpose of this method.Solar wrote:Crash, memory corruption, or nothing happening at all?QueueTsar wrote:...can't get it to work.
Is the overall idea unsound? Is there a way to force a page to stay out of the tlb?
giszo
Re: Copying memory for fork across page directories
If I've understood correctly, you are mapping a page from the parent process into the childs address space, duplicating then repeating with an incremented address?
If so I see no problem with that so long as you disable context switching to ensure the parent doesn't modify anything while you are copying. As you've mentioned you need to reload CR3 (or invlpg) each time you change the page tables.
Also you mentioned one TSS so I assume stack based context switching? Do you remember to clone the ring0 stack too?
If so I see no problem with that so long as you disable context switching to ensure the parent doesn't modify anything while you are copying. As you've mentioned you need to reload CR3 (or invlpg) each time you change the page tables.
Also you mentioned one TSS so I assume stack based context switching? Do you remember to clone the ring0 stack too?
All your base are belong to us.