+ if(expected != CHANGEABLE_BITS) {
+ Log("%016x-%016x => %013x-%013x (%s%s%s%s)",
+ rangeStart, curPos - 1,
+ PAGETABLE(rangeStart>>12) & ~0xFFF,
+ (expected & ~0xFFF) - 1,
+ (expected & PF_PAGED ? "p" : "-"),
+ (expected & PF_COW ? "C" : "-"),
+ (expected & PF_USER ? "U" : "-"),
+ (expected & PF_WRITE ? "W" : "-")
+ );
+ expected = 0;
+ }
+}
+
+/**
+ * \brief Get a pointer to a page entry
+ * \param Addr Virtual Address
+ * \param bTemp Use the Temporary fractal mapping
+ * \param bAllocate Allocate entries
+ * \param bLargePage Request a large page
+ * \param Pointer Location to place the calculated pointer
+ * \return Page size, or -ve on error
+ */
+int MM_GetPageEntryPtr(tVAddr Addr, BOOL bTemp, BOOL bAllocate, BOOL bLargePage, tPAddr **Pointer)
+{
+ tPAddr *pmlevels[4];
+ tPAddr tmp;
+ const int ADDR_SIZES[] = {39, 30, 21, 12};
+ const int nADDR_SIZES = sizeof(ADDR_SIZES)/sizeof(ADDR_SIZES[0]);
+ int i;
+
+ if( bTemp )
+ pmlevels[3] = (void*)MM_TMPFRAC_BASE; // Temporary Page Table
+ else
+ pmlevels[3] = (void*)MM_FRACTAL_BASE; // Page Table
+ pmlevels[2] = &pmlevels[3][(MM_FRACTAL_BASE>>12)&PAGE_MASK]; // PDIR
+ pmlevels[1] = &pmlevels[2][(MM_FRACTAL_BASE>>21)&TABLE_MASK]; // PDPT
+ pmlevels[0] = &pmlevels[1][(MM_FRACTAL_BASE>>30)&PDP_MASK]; // PML4
+// Log("pmlevels = {%p, %p, %p, %p}",
+// MM_FRACTAL_BASE>>30, MM_FRACTAL_BASE>>21, MM_FRACTAL_BASE>>12, MM_FRACTAL_BASE);
+// Log("pmlevels = {%p, %p, %p, %p}",
+// pmlevels[0], pmlevels[1], pmlevels[2], pmlevels[3]);
+
+ // Mask address
+ Addr &= (1ULL << 48)-1;
+
+ for( i = 0; i < nADDR_SIZES-1; i ++ )