- Share some more inline functions between the kernel and freeldr
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 13 Nov 2009 23:30:44 +0000 (23:30 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 13 Nov 2009 23:30:44 +0000 (23:30 +0000)
- Use __ltr instead of Ke386SetTr
- refactor KiInitializeTss
- Update some Mm conatnts
- Halfplement KeFlushEntireTb
- Clean the mapping of page 0 in KiSystemStartup, as long as we don't clean mappings in freeldr
- Fix a serious bug in KiPageFault, where ebp was used instead of rbp, resulting in recursive page faults as soon as usermode mappings were cleared
- Refactor MmArmInitSystem and related. Pahse 0 initialisation completes here now. we fail later in freelist setup code, which is not 64 bit safe.

svn path=/branches/ros-amd64-bringup/; revision=44144

reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
reactos/ntoskrnl/include/internal/amd64/intrin_i.h
reactos/ntoskrnl/include/internal/amd64/ke.h
reactos/ntoskrnl/include/internal/amd64/mm.h
reactos/ntoskrnl/ke/amd64/cpu.c
reactos/ntoskrnl/ke/amd64/kiinit.c
reactos/ntoskrnl/ke/amd64/trap.S
reactos/ntoskrnl/mm/amd64/init.c

index f050c3d..ea7e380 100644 (file)
@@ -58,28 +58,6 @@ typedef struct _PAGE_DIRECTORY_AMD64
     HARDWARE_PTE Pde[512];
 } PAGE_DIRECTORY_AMD64, *PPAGE_DIRECTORY_AMD64;
 
-PKGDTENTRY64
-FORCEINLINE
-KiGetGdtEntry(PVOID pGdt, USHORT Index)
-{
-    return (PKGDTENTRY64)((ULONG64)pGdt + (Index & ~RPL_MASK));
-}
-
-VOID
-FORCEINLINE
-KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Limit, UCHAR Type, UCHAR Dpl)
-{
-    Entry->Bits.Type = Type;
-    Entry->Bits.Present = 1;
-    Entry->Bits.Dpl = Dpl;
-    Entry->BaseLow = (USHORT)(Base & 0xFFFF);
-    Entry->Bytes.BaseMiddle = (UCHAR)(Base >> 16);
-    Entry->Bytes.BaseHigh = (UCHAR)(Base >> 24);
-    Entry->BaseUpper = (ULONG)(Base >> 32);
-    Entry->LimitLow = (USHORT)(Limit & 0xFFFF);
-    Entry->Bits.LimitHigh = (ULONG)((Limit >> 16) & 0xf);
-    Entry->MustBeZero = 0;
-}
 
 VOID FrLdrSetupGdtIdt();
 
index b14ee0a..e331536 100644 (file)
@@ -354,8 +354,8 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
        Ke386SetGs(KGDT_64_DATA | RPL_MASK);   // 0x2b
        Ke386SetSs(KGDT_64_R0_SS);             // 0x18
 
-       // Load TSR
-       Ke386SetTr(KGDT_TSS);
+       /* Load TSR */
+       __ltr(KGDT_TSS);
 
     DPRINTM(DPRINT_WINDOWS, "leave WinLdrSetProcessorContext\n");
 }
index 1bde178..ad1bf1b 100644 (file)
@@ -9,6 +9,57 @@
 
 #define KeSetCurrentIrql(x) __writecr8(x)
 
+PKGDTENTRY64
+FORCEINLINE
+KiGetGdtEntry(PVOID pGdt, USHORT Selector)
+{
+    return (PKGDTENTRY64)((ULONG64)pGdt + (Selector & ~RPL_MASK));
+}
+
+PVOID
+FORCEINLINE
+KiGetGdtDescriptorBase(PKGDTENTRY Entry)
+{
+    return (PVOID)((ULONG64)Entry->BaseLow |
+                   (ULONG64)Entry->Bytes.BaseMiddle << 16 |
+                   (ULONG64)Entry->Bytes.BaseHigh << 24 |
+                   (ULONG64)Entry->BaseUpper << 32);
+}
+
+VOID
+FORCEINLINE
+KiSetGdtDescriptorBase(PKGDTENTRY Entry, ULONG64 Base)
+{
+    Entry->BaseLow = Base & 0xffff;
+    Entry->Bits.BaseMiddle = (Base >> 16) & 0xff;
+    Entry->Bits.BaseHigh = (Base >> 24) & 0xff;
+    Entry->BaseUpper = Base >> 32;
+}
+
+PVOID
+FORCEINLINE
+KiSetGdtDescriptorLimit(PKGDTENTRY Entry, ULONG Limit)
+{
+    Entry->LimitLow = Limit & 0xffff;
+    Entry->Bits.LimitHigh = Limit >> 16;
+}
+
+VOID
+FORCEINLINE
+KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Size, UCHAR Type, UCHAR Dpl)
+{
+    KiSetGdtDescriptorBase(Entry, Base);
+    KiSetGdtDescriptorLimit(Entry, Size - 1);
+    Entry->Bits.Type = Type;
+    Entry->Bits.Dpl = Dpl;
+    Entry->Bits.Present = 1;
+    Entry->Bits.System = 0;
+    Entry->Bits.LongMode = 0;
+    Entry->Bits.DefaultBig = 0;
+    Entry->Bits.Granularity = 0;
+    Entry->MustBeZero = 0;
+}
+
 #if defined(__GNUC__)
 
 static __inline__ __attribute__((always_inline)) void __lgdt(void *Source)
@@ -41,9 +92,9 @@ static __inline__ __attribute__((always_inline)) void __stmxcsr(unsigned long *D
        __asm__ __volatile__("stmxcsr %0" : : "m"(*Destination) : "memory");
 }
 
-static __inline__ __attribute__((always_inline)) void __ltr(unsigned short *Source)
+static __inline__ __attribute__((always_inline)) void __ltr(unsigned short Source)
 {
-       __asm__ __volatile__("ltr %0" : : "m"(*Source));
+       __asm__ __volatile__("ltr %0" : : "rm"(Source));
 }
 
 static __inline__ __attribute__((always_inline)) void __str(unsigned short *Destination)
@@ -51,25 +102,6 @@ static __inline__ __attribute__((always_inline)) void __str(unsigned short *Dest
        __asm__ __volatile__("str %0" : : "m"(*Destination) : "memory");
 }
 
-#define Ke386GetLocalDescriptorTable(X) \
-    __asm__("sldt %0\n\t" \
-    : /* no outputs */ \
-    : "m" (X));
-
-#define Ke386SetLocalDescriptorTable(X) \
-    __asm__("lldt %w0\n\t" \
-    : /* no outputs */ \
-    : "q" (X));
-
-#define Ke386SetTr(X)                   __asm__ __volatile__("ltr %%ax" : :"a" (X));
-
-#define Ke386GetTr(X) \
-    __asm__("str %0\n\t" \
-    : /* no outputs */ \
-    : "m" (X));
-
-#define Ke386SaveFlags(x)        __asm__ __volatile__("pushfq ; popq %0":"=rm" (x): /* no input */)
-#define Ke386RestoreFlags(x)     __asm__ __volatile__("pushq %0 ; popfq": /* no output */ :"irm" (x):"memory")
 
 #define _Ke386GetSeg(N)           ({ \
                                      unsigned int __d; \
index 0778fe2..eeb3856 100644 (file)
@@ -46,6 +46,8 @@
 #define X86_MSR_CSTAR           0xC0000083
 #define X86_MSR_SFMASK          0xC0000084
 
+#define AMD64_TSS 9
+
 #ifndef __ASM__
 
 #include "intrin_i.h"
@@ -118,21 +120,10 @@ KeInvalidateTlbEntry(IN PVOID Address)
 }
 
 struct _KPCR;
-VOID
-KiInitializeGdt(struct _KPCR* Pcr);
-VOID
-Ki386ApplicationProcessorInitializeTSS(VOID);
-
-// Hack
-VOID KiRosPrepareForSystemStartup(ULONG, PROS_LOADER_PARAMETER_BLOCK);
 
 VOID
 FASTCALL
-Ki386InitializeTss(
-    IN PKTSS Tss,
-    IN PVOID GdtBase,
-    IN UINT64 Stack
-);
+KiInitializeTss(IN PKTSS Tss, IN UINT64 Stack);
 
 VOID KiDivideErrorFault();
 VOID KiDebugTrapOrFault();
index c326c85..90871e2 100644 (file)
@@ -5,11 +5,24 @@
 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_AMD64_MM_H
 #define __NTOSKRNL_INCLUDE_INTERNAL_AMD64_MM_H
 
+/* Helper macros */
 #define PAGE_MASK(x)           ((x)&(~0xfff))
 #define PAE_PAGE_MASK(x)       ((x)&(~0xfffLL))
 
-#define HYPER_SPACE 0xFFFFF70000000000ULL
-#define HYPER_SPACE_END   0xFFFFF77FFFFFFFFFULL
+/* Memory layout base addresses */
+#define HYPER_SPACE                            0xFFFFF70000000000ULL
+#define HYPER_SPACE_END                        0xFFFFF77FFFFFFFFFULL
+#define MI_SESSION_VIEW_END             (PVOID)0xFFFFF97FFF000000ULL
+#define MI_SESSION_SPACE_END            (PVOID)0xFFFFF98000000000ULL
+
+#define MI_PAGED_POOL_START             (PVOID)0xFFFFFA8000000000ULL
+
+#define MI_NON_PAGED_SYSTEM_START_MIN          0xFFFFFAA000000000ULL
+#define MI_NONPAGED_POOL_END            (PVOID)0xFFFFFAE000000000ULL
+
+#define MI_DEBUG_MAPPING                (PVOID)0xFFFFFFFF80000000ULL // FIXME
+
+
 
 PULONG64
 FORCEINLINE
@@ -87,8 +100,8 @@ MiAddressToPte(PVOID Address)
 #define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255*1024*1024) >> PAGE_SHIFT)
 #define MI_MIN_PAGES_FOR_SYSPTE_TUNING         ((19*1024*1024) >> PAGE_SHIFT)
 #define MI_MIN_PAGES_FOR_SYSPTE_BOOST          ((32*1024*1024) >> PAGE_SHIFT)
-#define MI_MAX_INIT_NONPAGED_POOL_SIZE         (128 * 1024 * 1024)
-#define MI_MAX_NONPAGED_POOL_SIZE              (128 * 1024 * 1024)
+#define MI_MAX_INIT_NONPAGED_POOL_SIZE         (128ULL * 1024 * 1024 * 1024)
+#define MI_MAX_NONPAGED_POOL_SIZE              (128ULL * 1024 * 1024 * 1024)
 #define MI_MAX_FREE_PAGE_LISTS                 4
 
 #define MI_MIN_INIT_PAGED_POOLSIZE             (32 * 1024 * 1024)
@@ -104,9 +117,6 @@ MiAddressToPte(PVOID Address)
 
 #define MI_SYSTEM_VIEW_SIZE                    (16 * 1024 * 1024)
 
-#define MI_PAGED_POOL_START                    (PVOID)0xFFFFFA8000000000ULL
-#define MI_NONPAGED_POOL_END                   (PVOID)0xFFFFFAE000000000ULL
-#define MI_DEBUG_MAPPING                       (PVOID)0xFFFFFFFF80000000ULL // FIXME
  
 #define MM_HIGHEST_VAD_ADDRESS \
     (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
index 9c0ad21..9156bd1 100644 (file)
@@ -46,6 +46,9 @@ BOOLEAN KiSMTProcessorsPresent;
 KIRQL KiOldIrql;
 ULONG KiFreezeFlag;
 
+/* Flush data */
+volatile LONG KiTbFlushTimeStamp;
+
 /* CPU Signatures */
 static const CHAR CmpIntelID[]       = "GenuineIntel";
 static const CHAR CmpAmdID[]         = "AuthenticAMD";
@@ -90,7 +93,7 @@ KiSetProcessorType(VOID)
     KeGetCurrentPrcb()->CpuID = 0;
 
     /* Save EFlags */
-    Ke386SaveFlags(EFlags);
+    EFlags = __readeflags();
 
     /* Do CPUID 1 now */
     __cpuid(Reg, 1);
@@ -115,7 +118,7 @@ KiSetProcessorType(VOID)
     KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
 
     /* Restore EFLAGS */
-    Ke386RestoreFlags(EFlags);
+    __writeeflags(EFlags);
 }
 
 ULONG
@@ -389,35 +392,19 @@ KiGetCacheInformation(VOID)
 
 VOID
 FASTCALL
-Ki386InitializeTss(IN PKTSS64 Tss,
-                   IN PVOID GdtBase,
-                   IN UINT64 Stack)
+KiInitializeTss(IN PKTSS64 Tss,
+                IN UINT64 Stack)
 {
     PKGDTENTRY64 TssEntry;
 
-    /* Initialize the TSS descriptor entry */
-    TssEntry = (PVOID)((ULONG64)GdtBase + KGDT_TSS);
-    TssEntry->Bits.Type = 9;//AMD64_TSS;
-    TssEntry->Bits.Dpl = 0;
-    TssEntry->Bits.Present = 1;
-    TssEntry->Bits.System = 0;
-    TssEntry->Bits.LongMode = 0;
-    TssEntry->Bits.DefaultBig = 0;
-    TssEntry->Bits.Granularity = 0;
-    TssEntry->MustBeZero = 0;
-
-    /* Descriptor base is the TSS address */
-    TssEntry->BaseLow = (ULONG64)Tss & 0xffff;
-    TssEntry->Bits.BaseMiddle = ((ULONG64)Tss >> 16) & 0xff;
-    TssEntry->Bits.BaseHigh = ((ULONG64)Tss >> 24) & 0xff;
-    TssEntry->BaseUpper = (ULONG64)Tss >> 32;
-
-    /* Set the limit */
-    TssEntry->LimitLow = sizeof(KTSS64) -1;
-    TssEntry->Bits.LimitHigh = 0;
+    /* Get pointer to the GDT entry */
+    TssEntry = KiGetGdtEntry(KeGetPcr()->GdtBase, KGDT_TSS);
+
+    /* Initialize the GDT entry */
+    KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0);
 
     /* Zero out the TSS */
-    RtlZeroMemory(Tss, sizeof(KTSS));
+    RtlZeroMemory(Tss, sizeof(KTSS64));
 
     /* FIXME: I/O Map? */
     Tss->IoMapBase = 0x68;
@@ -435,8 +422,7 @@ Ki386InitializeTss(IN PKTSS64 Tss,
     Tss->Ist[3] = (ULONG64)KiDoubleFaultStack;
 
     /* Load the task register */
-    Ke386SetTr(KGDT_TSS);
-
+    __ltr(KGDT_TSS);
 }
 
 VOID
@@ -535,7 +521,19 @@ NTAPI
 KeFlushEntireTb(IN BOOLEAN Invalid,
                 IN BOOLEAN AllProcessors)
 {
-    UNIMPLEMENTED;
+    KIRQL OldIrql;
+
+    // FIXME: halfplemented
+    /* Raise the IRQL for the TB Flush */
+    OldIrql = KeRaiseIrqlToSynchLevel();
+
+    /* Flush the TB for the Current CPU, and update the flush stamp */
+    KeFlushCurrentTb();
+
+    /* Update the flush stamp and return to original IRQL */
+    InterlockedExchangeAdd(&KiTbFlushTimeStamp, 1);
+    KeLowerIrql(OldIrql);
+
 }
 
 KAFFINITY
index 68f9af8..12ab2dd 100644 (file)
@@ -337,7 +337,7 @@ KiInitializePcr(IN PKIPCR Pcr,
                 IN PVOID DpcStack)
 {
     KDESCRIPTOR GdtDescriptor = {{0},0,0}, IdtDescriptor = {{0},0,0};
-    KGDTENTRY64 TssSelector;
+    PKGDTENTRY64 TssEntry;
     USHORT Tr = 0;
 
     /* Zero out the PCR */
@@ -375,19 +375,16 @@ KiInitializePcr(IN PKIPCR Pcr,
     Pcr->IdtBase = (PKIDTENTRY)IdtDescriptor.Base;
 
     /* Get TSS Selector */
-    Ke386GetTr(Tr); // <- FIXME: this is ugly!
-    if (Tr != KGDT_TSS) Tr = KGDT_TSS; // FIXME: HACKHACK
+    __str(&Tr);
+    ASSERT(Tr == KGDT_TSS);
 
-    /* Get TSS Selector, mask it and get its GDT Entry */
-    TssSelector = *(PKGDTENTRY)((ULONG_PTR)Pcr->GdtBase + (Tr & ~RPL_MASK));
+    /* Get TSS Entry */
+    TssEntry = KiGetGdtEntry(Pcr->GdtBase, Tr);
 
     /* Get the KTSS itself */
-    Pcr->TssBase = (PKTSS)(ULONG_PTR)(TssSelector.BaseLow |
-                              TssSelector.Bytes.BaseMiddle << 16 |
-                              TssSelector.Bytes.BaseHigh << 24 |
-                              (ULONG64)TssSelector.BaseUpper << 32);
+    Pcr->TssBase = KiGetGdtDescriptorBase(TssEntry);
 
-    Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
+    Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0; // FIXME
 
     /* Set DPC Stack */
     Pcr->Prcb.DpcStack = DpcStack;
@@ -403,7 +400,7 @@ KiInitializePcr(IN PKIPCR Pcr,
     Pcr->Prcb.CurrentThread = IdleThread;
 
     /* Start us out at PASSIVE_LEVEL */
-//    Pcr->Irql = PASSIVE_LEVEL;
+    Pcr->Irql = PASSIVE_LEVEL;
     KeSetCurrentIrql(PASSIVE_LEVEL);
 
 }
@@ -627,6 +624,9 @@ KiSystemStartup(IN ULONG_PTR Dummy,
     FrLdrDbgPrint = ((PLOADER_PARAMETER_BLOCK)Dummy)->u.I386.CommonDataArea;
     FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");
 
+    /* HACK, because freeldr maps page 0 */
+    MiAddressToPte((PVOID)0)->u.Hard.Valid = 0;
+
     KiSystemStartupReal((PLOADER_PARAMETER_BLOCK)Dummy);
 
 //    KiRosPrepareForSystemStartup(Dummy, LoaderBlock);
@@ -699,7 +699,7 @@ KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     if (Cpu == 0)
     {
         /* Setup the TSS descriptors and entries */
-        Ki386InitializeTss(Pcr->TssBase, Pcr->GdtBase, InitialStack);
+        KiInitializeTss(Pcr->TssBase, InitialStack);
 
         /* Setup the IDT */
         KeInitExceptions();
@@ -711,7 +711,7 @@ KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
         KdInitSystem(0, KeLoaderBlock);
 
         /* Check for break-in */
-//        if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
+        if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
 
         /* Hack! Wait for the debugger! */
         while (!KdPollBreakIn());
@@ -728,7 +728,7 @@ KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
 //    DPRINT1("Gdt = %p, Idt = %p, Pcr = %p, Tss = %p\n", Gdt, Idt, Pcr, Tss);
 
-    DbgBreakPointWithStatus(0);
+    DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
 
     /* Initialize the Processor with HAL */
     HalInitializeProcessor(Cpu, KeLoaderBlock);
index f59df0e..e7e6910 100644 (file)
@@ -19,7 +19,7 @@ _MsgUnimplemented:
 .asciz "WARNING:  %s at %s:%d is UNIMPLEMENTED!\n"
 
 _MsgPageFault:
-.ascii "Page fault 0x%x at %p!\n\0"
+.ascii "Page fault! Code = 0x%x, RIP = %p, FaultingAddress = %p\n\0"
 
 _MsgGeneralProtFault:
 .ascii "General protection fault at %p!\n\0"
@@ -333,9 +333,9 @@ KiDebugTrapOrFaultKMode:
 
     ENTER_TRAP_FRAME (0x28), TRAPFLAG_ALL
 
-    lea rcx, _MsgBreakpointTrap[rip]
-    mov rdx, rbp
-    call _FrLdrDbgPrint[rip]
+//    lea rcx, _MsgBreakpointTrap[rip]
+//    mov rdx, rsp
+//    call _FrLdrDbgPrint[rip]
 
     /* Dispatch the exception */
     mov ecx, STATUS_BREAKPOINT
@@ -495,23 +495,25 @@ KiDebugTrapOrFaultKMode:
     .pushframe 1
     /* We have an error code */
 
-//    lea rcx, _MsgPageFault[rip]
-//    mov rdx, [rsp]
-//    mov r8, [rsp+8]
-//    mov r9, rsp
-//    call _FrLdrDbgPrint[rip]
-
     ENTER_TRAP_FRAME (0x28), TRAPFLAG_ALL
 
+#if 0
+    lea rcx, _MsgPageFault[rip]
+    mov rdx, [rbp + KTRAP_FRAME_ErrorCode]
+    mov r8, [rbp + KTRAP_FRAME_Rip]
+    mov r9, [rbp + KTRAP_FRAME_FaultAddress]
+    call _FrLdrDbgPrint[rip]
+#endif
+
     /* Save page fault address */
     mov rdx, cr2
     mov [rbp  + KTRAP_FRAME_FaultAddress], rdx
 
     /* Call page fault handler */
-    mov ecx, [ebp + KTRAP_FRAME_ErrorCode] // StoreInstruction
+    mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // StoreInstruction
     and ecx, 1
     // rdx == Address
-    mov r8b, [ebp + KTRAP_FRAME_SegCs] // Mode
+    mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
     and r8b, 1
     mov r9, rbp // TrapInformation
 //    call _MmAccessFault
@@ -524,7 +526,7 @@ KiDebugTrapOrFaultKMode:
     jge PageFaultReturn
 
     /* Set parameter 1 to error code */
-    mov r9d, [ebp + KTRAP_FRAME_ErrorCode]
+    mov r9d, [rbp + KTRAP_FRAME_ErrorCode]
 
     /* Set parameter2 to faulting address */
     mov r10, cr2  // Param2 = faulting address
index 0be522f..8ff9a9b 100644 (file)
@@ -15,9 +15,7 @@
 
 #include "../ARM3/miarm.h"
 
-#define MI_SESSION_SPACE_END (PVOID)0xFFFFF98000000000ULL
-#define MI_SESSION_VIEW_END 0xFFFFF97FFF000000ULL
-#define MI_NON_PAGED_SYSTEM_START_MIN 0x0FFFFFAA000000000ULL
+extern PMMPTE MmDebugPte;
 
 /* GLOBALS *****************************************************************/
 
@@ -65,10 +63,11 @@ PVOID MmPagedPoolEnd;
 ULONG64 MmBootImageSize;
 PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
 RTL_BITMAP MiPfnBitMap;
-ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage = -1;
+ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage = -1; // FIXME: ULONG64
 ULONG64 MmNumberOfSystemPtes;
 PMMPTE MmSystemPagePtes;
 ULONG64 MxPfnAllocation;
+ULONG64 MxPfnSizeInBytes;
 
 PVOID MmSystemCacheStart;
 PVOID MmSystemCacheEnd;
@@ -83,24 +82,59 @@ MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
 PFN_NUMBER MxFreePageBase;
 ULONG64 MxFreePageCount = 0;
 
+ULONG
+NoDbgPrint(const char *Format, ...)
+{
+    return 0;
+}
+
 VOID
 NTAPI
-MxSetupFreePageList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+MiEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
     PLIST_ENTRY ListEntry;
+    PFN_NUMBER LastPage;
 
     /* Loop the memory descriptors */
     for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
          ListEntry != &LoaderBlock->MemoryDescriptorListHead;
          ListEntry = ListEntry->Flink)
     {
-        /* Get the memory block */
+        /* Get the memory descriptor */
         MdBlock = CONTAINING_RECORD(ListEntry,
                                     MEMORY_ALLOCATION_DESCRIPTOR,
                                     ListEntry);
 
-        /* Check if this is free memory */
+        /* Skip pages that are not part of the PFN database */
+        if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
+            (MdBlock->MemoryType == LoaderBBTMemory) ||
+            (MdBlock->MemoryType == LoaderHALCachedMemory) ||
+            (MdBlock->MemoryType == LoaderSpecialMemory) ||
+            (MdBlock->MemoryType == LoaderBad))
+        {
+            continue;
+        }
+
+        /* Add this to the total of pages */
+        MmNumberOfPhysicalPages += MdBlock->PageCount;
+
+        /* Check if this is the new lowest page */
+        if (MdBlock->BasePage < MmLowestPhysicalPage)
+        {
+            /* Update the lowest page */
+            MmLowestPhysicalPage = MdBlock->BasePage;
+        }
+
+        /* Check if this is the new highest page */
+        LastPage = MdBlock->BasePage + MdBlock->PageCount - 1;
+        if (LastPage > MmHighestPhysicalPage)
+        {
+            /* Update the highest page */
+            MmHighestPhysicalPage = LastPage;
+        }
+
+        /* Check if this is currently free memory */
         if ((MdBlock->MemoryType == LoaderFree) ||
             (MdBlock->MemoryType == LoaderLoadedProgram) ||
             (MdBlock->MemoryType == LoaderFirmwareTemporary) ||
@@ -142,14 +176,17 @@ MxGetNextPage(IN PFN_NUMBER PageCount)
     return Pfn;
 }
 
-VOID
-MxMapPage(PVOID Address)
+PMMPTE
+NTAPI
+MxGetPte(PVOID Address)
 {
     PMMPTE Pte;
     MMPTE TmpPte;
 
+    /* Setup template pte */
     TmpPte.u.Long = 0;
-    TmpPte.u.Hard.Valid = 1;
+    TmpPte.u.Flush.Valid = 1;
+    TmpPte.u.Flush.Write = 1;
 
     /* Get a pointer to the PXE */
     Pte = MiAddressToPxe(Address);
@@ -180,37 +217,108 @@ MxMapPage(PVOID Address)
 
     /* Get a pointer to the PTE */
     Pte = MiAddressToPte(Address);
-    if (!Pte->u.Hard.Valid)
-    {
-        /* It's not valid, map it! */
-        TmpPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
-        *Pte = TmpPte;
-    }
+    return Pte;
 }
 
 VOID
 MxMapPageRange(PVOID Address, ULONG64 PageCount)
 {
-    ULONG64 i;
+    MMPTE TmpPte, *Pte;
 
-    for (i = 0; i < PageCount; i++)
+    /* Setup template pte */
+    TmpPte.u.Long = 0;
+    TmpPte.u.Flush.Valid = 1;
+    TmpPte.u.Flush.Write = 1;
+
+    while (PageCount--)
     {
-        MxMapPage(Address);
+        /* Get the PTE for that page */
+        Pte = MxGetPte(Address);
+        ASSERT(Pte->u.Hard.Valid == 0);
+
+        /* Map a physical page */
+        TmpPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
+        *Pte = TmpPte;
+
+        /* Goto next page */
         Address = (PVOID)((ULONG64)Address + PAGE_SIZE);
     }
 }
 
-
 VOID
 NTAPI
-MiArmIninializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+MiArmConfigureMemorySizes(IN PLOADER_PARAMETER_BLOCK LoaderBloc)
 {
     /* Get the size of the boot loader's image allocations */
-    MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned;
-    MmBootImageSize *= PAGE_SIZE;
-    MmBootImageSize = (MmBootImageSize + (4 * 1024 * 1024) - 1) & ~((4 * 1024 * 1024) - 1);
-    ASSERT((MmBootImageSize % (4 * 1024 * 1024)) == 0);
+    MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned * PAGE_SIZE;
+    MmBootImageSize = ROUND_UP(MmBootImageSize, 4 * 1024 * 1024);
 
+    /* Check if this is a machine with less than 256MB of RAM, and no overide */
+    if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
+        !(MmSizeOfNonPagedPoolInBytes))
+    {
+        /* Force the non paged pool to be 2MB so we can reduce RAM usage */
+        MmSizeOfNonPagedPoolInBytes = 2 * 1024 * 1024;
+    }
+
+    /* Check if the user gave a ridicuously large nonpaged pool RAM size */
+    if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) >
+        (MmNumberOfPhysicalPages * 7 / 8))
+    {
+        /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
+        MmSizeOfNonPagedPoolInBytes = 0;
+    }
+
+    /* Check if no registry setting was set, or if the setting was too low */
+    if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize)
+    {
+        /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */
+        MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
+        MmSizeOfNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
+                                       256 * MmMinAdditionNonPagedPoolPerMb;
+    }
+
+    /* Check if the registy setting or our dynamic calculation was too high */
+    if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE)
+    {
+        // Set it to the maximum */
+        MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE;
+    }
+
+    /* Check if a percentage cap was set through the registry */
+    if (MmMaximumNonPagedPoolPercent)
+    {
+        /* Don't feel like supporting this right now */
+        UNIMPLEMENTED;
+    }
+
+    /* Page-align the nonpaged pool size */
+    MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1);
+    
+    /* Now, check if there was a registry size for the maximum size */
+    if (!MmMaximumNonPagedPoolInBytes)
+    {
+        /* Start with the default (1MB) and add 400 KB for each MB above 4 */
+        MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
+        MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
+                                         256 * MmMaxAdditionNonPagedPoolPerMb;
+    }
+    
+    /* Don't let the maximum go too high */
+    if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE)
+    {
+        /* Set it to the upper limit */
+        MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
+    }
+
+    // MmSessionImageSize
+}
+
+VOID
+NTAPI
+MiArmInitializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    /* Set up session space */
     MiSessionSpaceEnd = (PVOID)MI_SESSION_SPACE_END;
 
     /* This is where we will load Win32k.sys and the video driver */
@@ -220,7 +328,7 @@ MiArmIninializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
     /* The view starts right below the session working set (itself below
      * the image area) */
-    MiSessionViewEnd = (PVOID)MI_SESSION_VIEW_END;
+    MiSessionViewEnd = MI_SESSION_VIEW_END;
     MiSessionViewStart = (PVOID)((ULONG_PTR)MiSessionViewStart -
                                  MmSessionViewSize);
 
@@ -232,9 +340,6 @@ MiArmIninializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     /* And it all begins here */
     MmSessionBase = MiSessionPoolStart;
 
-    // Sanity check that our math is correct
-    //ASSERT((ULONG_PTR)MmSessionBase + MmSessionSize == PTE_BASE);
-
     /* System view space ends at session space, so now that we know where
      * this is, we can compute the base address of system view space itself. */
     MiSystemViewStart = (PVOID)((ULONG_PTR)MmSessionBase -
@@ -243,42 +348,86 @@ MiArmIninializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     /* Use the default */
     MmNumberOfSystemPtes = 22000;
 
-    /* FIXME: should start below paged pool */
-    MmPfnDatabase = (PVOID)0xFFFFFD5FC0000000ULL;
-
+    ASSERT(MiSessionViewEnd <= MiSessionImageStart);
+    ASSERT(MmSessionBase <= MiSessionPoolStart);
 }
 
 VOID
 MiArmInitializePageTable()
 {
     ULONG64 PageFrameOffset;
-    PMMPTE StartPte, EndPte;
+    PMMPTE Pte, StartPte, EndPte;
+
+    /* Get current directory base */
+    PageFrameOffset = ((PMMPTE)PXE_SELFMAP)->u.Hard.PageFrameNumber << PAGE_SHIFT;
+    ASSERT(PageFrameOffset == __readcr3());
 
-    /* Set CR3 for the system process */
-    PageFrameOffset = ((PMMPTE)PXE_BASE)->u.Hard.PageFrameNumber << PAGE_SHIFT;
+    /* Set directory base for the system process */
     PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameOffset;
 
+    /* HACK: don't use freeldr debug pront anymore */
+    FrLdrDbgPrint = NoDbgPrint;
+
+#if 1
     /* Clear user mode mappings in PML4 */
     StartPte = MiAddressToPxe(0);
-    EndPte = MiAddressToPxe(MmSystemRangeStart);
-    RtlZeroMemory(StartPte, (EndPte - StartPte) * sizeof(MMPTE));
+    EndPte = MiAddressToPxe(MmHighestUserAddress);
+
+    for (Pte = StartPte; Pte <= EndPte; Pte++)
+    {
+        /* Zero the pte */
+        Pte->u.Long = 0;
+    }
+#else
+    /* Clear user mode mappings in PML4 */
+    StartPte = MiAddressToPte(0);
+    EndPte = MiAddressToPte((PVOID)0xa00000);
+
+    for (Pte = StartPte; Pte < EndPte; Pte++)
+    {
+        /* Zero the pte */
+        //Pte->u.Long = 0;
+    }
+
+    /* Flush the TLB */
+    KeFlushCurrentTb();
+
+//    MiAddressToPde(0)->u.Long = 0;
+//    MiAddressToPde((PVOID)0x200000)->u.Long = 0;
+//    MiAddressToPde((PVOID)0x400000)->u.Long = 0;
+//    MiAddressToPde((PVOID)0x600000)->u.Long = 0;
+//    MiAddressToPde((PVOID)0x800000)->u.Long = 0;
+
+   // MiAddressToPpe->u.Long = 0;
+
+#endif
+
+    /* Flush the TLB */
+    KeFlushCurrentTb();
+
+    /* Setup debug mapping pte */
+    MmDebugPte = MxGetPte(MI_DEBUG_MAPPING);
 }
 
 
 VOID
 NTAPI
-MiArmEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+MiArmPreparePfnDatabse(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
     PLIST_ENTRY ListEntry;
-    PFN_NUMBER BasePage, LastPage, PageCount;
+    PFN_COUNT PageCount;
+    PVOID PageBase;
+
+    /* The PFN database is at the start of the non paged region */
+    MmPfnDatabase = (PVOID)((ULONG64)MmNonPagedPoolEnd - MmMaximumNonPagedPoolInBytes);
 
     /* Loop the memory descriptors */
     for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
          ListEntry != &LoaderBlock->MemoryDescriptorListHead;
          ListEntry = ListEntry->Flink)
     {
-        /* Get the descriptor */
+        /* Get the memory descriptor */
         MdBlock = CONTAINING_RECORD(ListEntry,
                                     MEMORY_ALLOCATION_DESCRIPTOR,
                                     ListEntry);
@@ -286,115 +435,43 @@ MiArmEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
         /* Skip pages that are not part of the PFN database */
         if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
             (MdBlock->MemoryType == LoaderBBTMemory) ||
-            (MdBlock->MemoryType == LoaderHALCachedMemory) || // ???
-            (MdBlock->MemoryType == LoaderSpecialMemory))
+            (MdBlock->MemoryType == LoaderHALCachedMemory) ||
+            (MdBlock->MemoryType == LoaderSpecialMemory) ||
+            (MdBlock->MemoryType != LoaderBad))
         {
             continue;
         }
 
-        /* Check if BURNMEM was used */
-        if (MdBlock->MemoryType != LoaderBad)
-        {
-            /* Count this in the total of pages */
-            MmNumberOfPhysicalPages += MdBlock->PageCount;
-        }
-
-        BasePage = MdBlock->BasePage;
-        LastPage = MdBlock->BasePage + MdBlock->PageCount - 1;
-
-        /* Check if this is the new lowest page */
-        if (BasePage < MmLowestPhysicalPage)
-        {
-            /* Update the lowest page */
-            MmLowestPhysicalPage = BasePage;
-        }
-
-        /* Check if this is the new highest page */
-        if (LastPage > MmHighestPhysicalPage)
-        {
-            /* Update the highest page */
-            MmHighestPhysicalPage = LastPage;
-        }
-DPRINT1("BasePage = %ld, LastPage = %ld\n", BasePage, LastPage);
-__debugbreak();
         /* Map pages for the PFN database */
-        PageCount = PAGE_ROUND_UP(MdBlock->PageCount * sizeof(MMPFN)) / PAGE_SIZE;
-        MxMapPageRange(&MmPfnDatabase[BasePage], PageCount);
+        PageCount = ROUND_TO_PAGES(MdBlock->PageCount * sizeof(MMPFN)) / PAGE_SIZE;
+        PageBase = PAGE_ALIGN(&MmPfnDatabase[MdBlock->BasePage]);
+        MxMapPageRange(PageBase, PageCount);
 
         /* Zero out the pages */
-        RtlZeroMemory(&MmPfnDatabase[BasePage], PageCount * PAGE_SIZE);
+        RtlZeroMemory(PageBase, PageCount * PAGE_SIZE);
     }
 
     /* Calculate the number of bytes, and then convert to pages */
-    MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
-    MxPfnAllocation >>= PAGE_SHIFT;
-    MxPfnAllocation++;
+    MxPfnSizeInBytes = ROUND_TO_PAGES(MmHighestPhysicalPage + 1) * sizeof(MMPFN);
+    MxPfnAllocation = MxPfnSizeInBytes >> PAGE_SHIFT;
 
+    /* Reduce maximum pool size */
+    MmMaximumNonPagedPoolInBytes -= MxPfnSizeInBytes;
 }
 
+
 VOID
 NTAPI
 MiArmPrepareNonPagedPool()
 {
     PFN_NUMBER PageCount;
+    PVOID Address;
 
-    /* Check if this is a machine with less than 256MB of RAM, and no overide */
-    if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
-        !(MmSizeOfNonPagedPoolInBytes))
-    {
-        /* Force the non paged pool to be 2MB so we can reduce RAM usage */
-        MmSizeOfNonPagedPoolInBytes = 2 * 1024 * 1024;
-    }
-
-    /* Check if the user gave a ridicuously large nonpaged pool RAM size */
-    if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) >
-        (MmNumberOfPhysicalPages * 7 / 8))
-    {
-        /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
-        MmSizeOfNonPagedPoolInBytes = 0;
-    }
-
-    /* Check if no registry setting was set, or if the setting was too low */
-    if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize)
-    {
-        /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */
-        MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
-        MmSizeOfNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
-                                       256 * MmMinAdditionNonPagedPoolPerMb;
-    }
-
-    /* Check if the registy setting or our dynamic calculation was too high */
-    if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE)
-    {
-        // Set it to the maximum */
-        MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE;
-    }
-
-    /* Check if a percentage cap was set through the registry */
-    if (MmMaximumNonPagedPoolPercent)
-    {
-        /* Don't feel like supporting this right now */
-        UNIMPLEMENTED;
-    }
-
-    /* Page-align the nonpaged pool size */
-    MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1);
-    
-    /* Now, check if there was a registry size for the maximum size */
-    if (!MmMaximumNonPagedPoolInBytes)
-    {
-        /* Start with the default (1MB) and add 400 KB for each MB above 4 */
-        MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
-        MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
-                                         256 * MmMaxAdditionNonPagedPoolPerMb;
-    }
-    
-    /* Don't let the maximum go too high */
-    if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE)
-    {
-        /* Set it to the upper limit */
-        MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
-    }
+    /* Non paged pool comes after the PFN database */
+    MmNonPagedPoolStart = (PVOID)((ULONG64)MmPfnDatabase +
+                                  MxPfnSizeInBytes);
+    ASSERT((ULONG64)MmNonPagedPoolEnd == (ULONG64)MmNonPagedPoolStart +
+                                  MmMaximumNonPagedPoolInBytes);
 
     /* Calculate the nonpaged pool expansion start region */
     MmNonPagedPoolExpansionStart = (PVOID)((ULONG_PTR)MmNonPagedPoolEnd -
@@ -402,9 +479,6 @@ MiArmPrepareNonPagedPool()
                                   MmSizeOfNonPagedPoolInBytes);
     MmNonPagedPoolExpansionStart = (PVOID)PAGE_ALIGN(MmNonPagedPoolExpansionStart);
 
-    DPRINT("NP Pool has been tuned to: %d bytes and %d bytes\n",
-           MmSizeOfNonPagedPoolInBytes, MmMaximumNonPagedPoolInBytes);
-
     /* Now calculate the nonpaged system VA region, which includes the
      * nonpaged pool expansion (above) and the system PTEs. Note that it is
      * then aligned to a PDE boundary (4MB). */
@@ -427,15 +501,21 @@ MiArmPrepareNonPagedPool()
         ASSERT(MmNumberOfSystemPtes > 1000);
     }
 
-    /* Non paged pool comes after the PFN database */
-    MmNonPagedPoolStart = (PVOID)((ULONG_PTR)MmPfnDatabase +
-                                  (MxPfnAllocation << PAGE_SHIFT));
-
     /* Map the nonpaged pool */
     PageCount = (MmSizeOfNonPagedPoolInBytes + PAGE_SIZE - 1) / PAGE_SIZE;
     MxMapPageRange(MmNonPagedPoolStart, PageCount);
 
-    /* Sanity check: make sure we have properly defined the system PTE space */
+    /* Create PTEs for the paged pool extension */
+    for (Address = MmNonPagedPoolExpansionStart;
+         Address < MmNonPagedPoolEnd;
+         Address = (PVOID)((ULONG64)Address + PAGE_SIZE))
+    {
+        /* Create PXE, PPE, PDE and set PTE to 0*/
+        MxGetPte(Address)->u.Long = 0;
+    }
+
+//DPRINT1("MmNonPagedPoolStart = %p, Pte=%p \n", MmNonPagedPoolStart, MiAddressToPte(MmNonPagedPoolStart));
+    /* Sanity check */
     ASSERT(MiAddressToPte(MmNonPagedSystemStart) <
            MiAddressToPte(MmNonPagedPoolExpansionStart));
 
@@ -448,18 +528,22 @@ MmArmInitSystem(IN ULONG Phase,
 {
     if (Phase == 0)
     {
-        /* Get a continuous range of physical pages */
-        MxSetupFreePageList(LoaderBlock);
+        /* Parse memory descriptors */
+        MiEvaluateMemoryDescriptors(LoaderBlock);
+
+        /* Configure the memory sizes */
+        MiArmConfigureMemorySizes(LoaderBlock);
 
         /* Initialize the memory layout */
-        MiArmIninializeMemoryLayout(LoaderBlock);
+        MiArmInitializeMemoryLayout(LoaderBlock);
 
-        /* Loop descriptors and prepare PFN database */
-        MiArmEvaluateMemoryDescriptors(LoaderBlock);
+        /* Prepare PFN database mappings */
+        MiArmPreparePfnDatabse(LoaderBlock);
 
+        /* Initialize some mappings */
         MiArmInitializePageTable();
 
-        /* Configure size of the non paged pool */
+        /* Prepare paged pool mappings */
         MiArmPrepareNonPagedPool();
 
         /* Initialize the ARM3 nonpaged pool */
@@ -476,6 +560,7 @@ MmArmInitSystem(IN ULONG Phase,
         /* The PFN database was created, restore the free descriptor */
         *MxFreeDescriptor = MxOldFreeDescriptor;
 
+        ASSERT(FALSE);
 
     }