Merge from amd64 branch:
[reactos.git] / reactos / boot / freeldr / freeldr / windows / amd64 / wlmemory.c
index ef6a18d..3e3288a 100644 (file)
 
 //extern ULONG LoaderPagesSpanned;
 
-// This is needed because headers define wrong one for ReactOS
-#undef KIP0PCRADDRESS
-#define KIP0PCRADDRESS                      0xffdff000
-
-#define HYPER_SPACE_ENTRY       0x300
-
-// This is needed only for SetProcessorContext routine
-#pragma pack(2)
-       typedef struct
-       {
-               USHORT Limit;
-               ULONG Base;
-       } GDTIDT;
-#pragma pack(4)
+#define HYPER_SPACE_ENTRY       0x1EE
 
 /* GLOBALS ***************************************************************/
 
-//PHARDWARE_PTE PDE;
+PHARDWARE_PTE PxeBase;
 //PHARDWARE_PTE HalPageTable;
 
-PPAGE_DIRECTORY_AMD64 pPML4;
 
 /* FUNCTIONS **************************************************************/
 
 BOOLEAN
 MempAllocatePageTables()
 {
-       ULONG KernelPages;
-       PVOID UserSharedData;
-
     DPRINTM(DPRINT_WINDOWS,">>> MempAllocatePageTables\n");
 
        /* Allocate a page for the PML4 */
-       pPML4 = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
-    if (!pPML4)
+       PxeBase = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+    if (!PxeBase)
     {
         DPRINTM(DPRINT_WINDOWS,"failed to allocate PML4\n");
         return FALSE;
@@ -58,14 +41,14 @@ MempAllocatePageTables()
        // FIXME: Physical PTEs = FirmwareTemporary ?
 
        /* Zero the PML4 */
-       RtlZeroMemory(pPML4, PAGE_SIZE);
+       RtlZeroMemory(PxeBase, PAGE_SIZE);
 
        /* The page tables are located at 0xfffff68000000000 
         * We create a recursive self mapping through all 4 levels at 
         * virtual address 0xfffff6fb7dbedf68 */
-       pPML4->Pde[VAtoPXI(PXE_BASE)].Valid = 1;
-       pPML4->Pde[VAtoPXI(PXE_BASE)].Write = 1;
-       pPML4->Pde[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(pPML4);
+       PxeBase[VAtoPXI(PXE_BASE)].Valid = 1;
+       PxeBase[VAtoPXI(PXE_BASE)].Write = 1;
+       PxeBase[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(PxeBase);
 
     // FIXME: map PDE's for hals memory mapping
 
@@ -74,65 +57,97 @@ MempAllocatePageTables()
        return TRUE;
 }
 
-PPAGE_DIRECTORY_AMD64
-MempGetOrCreatePageDir(PPAGE_DIRECTORY_AMD64 pDir, ULONG Index)
+PHARDWARE_PTE
+MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
 {
-       PPAGE_DIRECTORY_AMD64 pSubDir;
+       PHARDWARE_PTE SubDir;
 
-       if (!pDir)
+       if (!PdeBase)
                return NULL;
 
-       if (!pDir->Pde[Index].Valid)
+       if (!PdeBase[Index].Valid)
        {
-               pSubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderSpecialMemory);
-               if (!pSubDir)
+               SubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+               if (!SubDir)
                        return NULL;
-               RtlZeroMemory(pSubDir, PAGE_SIZE);
-               pDir->Pde[Index].PageFrameNumber = PtrToPfn(pSubDir);
-               pDir->Pde[Index].Valid = 1;
-               pDir->Pde[Index].Write = 1;
+               RtlZeroMemory(SubDir, PAGE_SIZE);
+               PdeBase[Index].PageFrameNumber = PtrToPfn(SubDir);
+               PdeBase[Index].Valid = 1;
+               PdeBase[Index].Write = 1;
        }
        else
        {
-               pSubDir = (PPAGE_DIRECTORY_AMD64)((ULONGLONG)(pDir->Pde[Index].PageFrameNumber) * PAGE_SIZE);
+               SubDir = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
        }
-       return pSubDir;
+       return SubDir;
 }
 
 BOOLEAN
-MempMapSinglePage(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress)
+MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
 {
-       PPAGE_DIRECTORY_AMD64 pDir3, pDir2, pDir1;
+       PHARDWARE_PTE PpeBase, PdeBase, PteBase;
        ULONG Index;
 
-       pDir3 = MempGetOrCreatePageDir(pPML4, VAtoPXI(VirtualAddress));
-       pDir2 = MempGetOrCreatePageDir(pDir3, VAtoPPI(VirtualAddress));
-       pDir1 = MempGetOrCreatePageDir(pDir2, VAtoPDI(VirtualAddress));
+       PpeBase = MempGetOrCreatePageDir(PxeBase, VAtoPXI(VirtualAddress));
+       PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(VirtualAddress));
+       PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
 
-       if (!pDir1)
+       if (!PteBase)
+       {
+        DPRINTM(DPRINT_WINDOWS,"!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
                return FALSE;
+       }
 
        Index = VAtoPTI(VirtualAddress);
-       if (pDir1->Pde[Index].Valid)
+       if (PteBase[Index].Valid)
        {
+        DPRINTM(DPRINT_WINDOWS,"!!!Already mapped %ld\n", Index);
                return FALSE;
        }
 
-       pDir1->Pde[Index].Valid = 1;
-       pDir1->Pde[Index].Write = 1;
-       pDir1->Pde[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+       PteBase[Index].Valid = 1;
+       PteBase[Index].Write = 1;
+       PteBase[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
 
        return TRUE;
 }
 
+BOOLEAN
+MempIsPageMapped(PVOID VirtualAddress)
+{
+       PHARDWARE_PTE PpeBase, PdeBase, PteBase;
+    ULONG Index;
+    
+    Index = VAtoPXI(VirtualAddress);
+    if (!PxeBase[Index].Valid)
+        return FALSE;
+
+    PpeBase = (PVOID)((ULONG64)(PxeBase[Index].PageFrameNumber) * PAGE_SIZE);
+    Index = VAtoPPI(VirtualAddress);
+    if (!PpeBase[Index].Valid)
+        return FALSE;
+
+    PdeBase = (PVOID)((ULONG64)(PpeBase[Index].PageFrameNumber) * PAGE_SIZE);
+    Index = VAtoPDI(VirtualAddress);
+    if (!PdeBase[Index].Valid)
+        return FALSE;
+
+    PteBase = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
+    Index = VAtoPTI(VirtualAddress);
+    if (!PteBase[Index].Valid)
+        return FALSE;
+
+    return TRUE;
+}
+
 ULONG
-MempMapRangeOfPages(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress, ULONG cPages)
+MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, ULONG cPages)
 {
        ULONG i;
 
        for (i = 0; i < cPages; i++)
        {
-               if (!FrLdrMapSinglePage(VirtualAddress, PhysicalAddress))
+               if (!MempMapSinglePage(VirtualAddress, PhysicalAddress))
                {
                        return i;
                }
@@ -146,13 +161,24 @@ BOOLEAN
 MempSetupPaging(IN ULONG StartPage,
                                IN ULONG NumberOfPages)
 {
-    DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld)\n", StartPage, NumberOfPages);
+    DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld, %p)\n", 
+            StartPage, NumberOfPages, StartPage * PAGE_SIZE + KSEG0_BASE);
 
+    /* Identity mapping */
     if (MempMapRangeOfPages(StartPage * PAGE_SIZE,
                             StartPage * PAGE_SIZE,
                             NumberOfPages) != NumberOfPages)
     {
-        DPRINTM(DPRINT_WINDOWS,"Failed to map pages\n");
+        DPRINTM(DPRINT_WINDOWS,"Failed to map pages 1\n");
+        return FALSE;
+    }
+
+    /* Kernel mapping */
+    if (MempMapRangeOfPages(StartPage * PAGE_SIZE + KSEG0_BASE,
+                            StartPage * PAGE_SIZE,
+                            NumberOfPages) != NumberOfPages)
+    {
+        DPRINTM(DPRINT_WINDOWS,"Failed to map pages 2\n");
         return FALSE;
     }
 
@@ -201,14 +227,14 @@ BOOLEAN
 WinLdrMapSpecialPages(ULONG PcrBasePage)
 {
     /* Map the PCR page */
-    if (!MempMapSinglePage(PcrBasePage * PAGE_SIZE, KIP0PCRADDRESS))
+    if (!MempMapSinglePage(KIP0PCRADDRESS, PcrBasePage * PAGE_SIZE))
     {
         DPRINTM(DPRINT_WINDOWS, "Could not map PCR @ %lx\n", PcrBasePage);
         return FALSE;
     }
 
     /* Map KI_USER_SHARED_DATA */
-    if (!MempMapSinglePage((PcrBasePage+1) * PAGE_SIZE, KI_USER_SHARED_DATA))
+    if (!MempMapSinglePage(KI_USER_SHARED_DATA, (PcrBasePage+1) * PAGE_SIZE))
     {
         DPRINTM(DPRINT_WINDOWS, "Could not map KI_USER_SHARED_DATA\n");
         return FALSE;
@@ -284,6 +310,8 @@ WinLdrSetupIdt(PVOID IdtBase)
 VOID
 WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
 {
+    DPRINTM(DPRINT_WINDOWS, "WinLdrSetProcessorContext %p\n", Pcr);
+
        /* Disable Interrupts */
        _disable();
 
@@ -291,21 +319,31 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
        __writeeflags(0);
 
        /* Set the new PML4 */
-       __writecr3((ULONGLONG)pPML4);
+       __writecr3((ULONG64)PxeBase);
 
-       // Enable paging by modifying CR0
-       __writecr0(__readcr0() | CR0_PG);
+    /* Get kernel mode address of gdt / idt */
+       GdtIdt = (PVOID)((ULONG64)GdtIdt + KSEG0_BASE);
 
-       // Kernel expects the PCR to be zero-filled on startup
-       // FIXME: Why zero it here when we can zero it right after allocation?
-       RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
+    /* Create gdt entries and load gdtr */
+    WinLdrSetupGdt(GdtIdt, Tss);
 
-       RtlZeroMemory(GdtIdt, PAGE_SIZE);
+    /* Copy old Idt and set idtr */
+    WinLdrSetupIdt((PVOID)((ULONG64)GdtIdt + 2048)); // HACK!
 
-    WinLdrSetupGdt(GdtIdt, Tss);
+    /* LDT is unused */
+//    __lldt(0);
+
+    /* Load selectors for DS/ES/FS/GS/SS */
+    Ke386SetDs(KGDT_64_DATA | RPL_MASK);   // 0x2b
+    Ke386SetEs(KGDT_64_DATA | RPL_MASK);   // 0x2b
+    Ke386SetFs(KGDT_32_R3_TEB | RPL_MASK); // 0x53
+       Ke386SetGs(KGDT_64_DATA | RPL_MASK);   // 0x2b
+       Ke386SetSs(KGDT_64_R0_SS);             // 0x18
 
-    WinLdrSetupIdt(GdtIdt);
+       /* Load TSR */
+       __ltr(KGDT_TSS);
 
+    DPRINTM(DPRINT_WINDOWS, "leave WinLdrSetProcessorContext\n");
 }
 
 VOID