Page 1 of 1

Copying memory for fork across page directories

Posted: Mon Apr 20, 2009 4:31 am
by QueueTsar
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 =)

Re: Copying memory for fork across page directories

Posted: Mon Apr 20, 2009 5:06 am
by Solar
QueueTsar wrote:...can't get it to work.
Crash, memory corruption, or nothing happening at all?

Re: Copying memory for fork across page directories

Posted: Mon Apr 20, 2009 5:38 am
by QueueTsar
Solar wrote:
QueueTsar wrote:...can't get it to work.
Crash, memory corruption, or nothing happening at all?
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.

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

Posted: Mon Apr 20, 2009 7:21 am
by jal
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.
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?


JAL

Re: Copying memory for fork across page directories

Posted: Mon Apr 20, 2009 7:41 am
by giszo
QueueTsar wrote:
Solar wrote:
QueueTsar wrote:...can't get it to work.
Crash, memory corruption, or nothing happening at all?
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.

Is the overall idea unsound? Is there a way to force a page to stay out of the tlb?
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.

giszo

Re: Copying memory for fork across page directories

Posted: Mon Apr 20, 2009 8:19 am
by dosfan
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?