//========================================================= // Copy the given page and all consecutive subsequent ones //========================================================= void CopyPages(long address, struct Task *task) { address &= PageMask; // Get physical address of current PT struct PML4 *pml4 = (struct PML4 *) (task->cr3); struct PML4 *current_pml4 = (struct PML4 *) (currentTask->cr3); while (1) { struct PT *pt = GetPT(pml4, address, task->pid); struct PT *currentPT = GetPT(current_pml4, address, currentTask->pid); int i = GetPTIndex(address); if (!(VIRT(PT,currentPT) ->entries[i].value)) break; // Copy the physical memory p_Address data = AllocPage(task->pid); //data += VAddr / 8; CreatePTEWithPT((struct PML4 *)task->cr3, data, address, task->pid, US | RW | P | 0x800); memcpy( (void *) PAGE(((VIRT(PT, pt)) ->entries[i].value)) + VAddr, (void *) PAGE(((VIRT(PT, currentPT)) ->entries[i].value)) + VAddr, PageSize); address += PageSize; } }
//===================================================== // Create a Page Table for a new process // Return a pointer to the Page Directory of this table //===================================================== void * VCreatePageDir(unsigned short pid, unsigned short parentPid) { struct PML4 *pml4; struct PD *pd; // Allocate the base page for the Page Table pml4 = (struct PML4 *) AllocPage(pid); VIRT(PML4,pml4) ->entries[GetPML4Index(VAddr)].value = virtualPDP | P | RW; // Physical to virtual addresses pd = GetPD(pml4, 0, pid); VIRT(PD,pd) ->entries[GetPDIndex(0)].value = kernelPT | P | RW; // Kernel entries if (parentPid == 0) // Just create some default PTEs // We need these two entries so that NewKernelTask can // access the data and stack pages of the new process. { long c; struct PT *pt = GetPT(pml4, UserData, pid); VIRT(PT,pt) ->entries[GetPTIndex(UserData)].value = AllocAndCreatePTE(TempUserData, pid, RW | P); c = TempUserData; asm ("invlpg %0;" : :"m"(*(char *)TempUserData) ); pt = GetPT(pml4, KernelStack, pid); VIRT(PT,pt) ->entries[GetPTIndex(KernelStack)].value = AllocAndCreatePTE(TempUStack, pid, RW | P); pt = GetPT(pml4, UserStack, pid); VIRT(PT,pt) ->entries[GetPTIndex(UserStack)].value = AllocAndCreatePTE(TempUStack, pid, RW | P); c = TempUStack; asm ("invlpg %0;" : :"m"(*(char *)TempUStack) ); }