- Detect more cpu features.

- Implemented the noexecute protection for the AMD64 cpu.

svn path=/trunk/; revision=11075
This commit is contained in:
Hartmut Birr 2004-09-26 16:32:18 +00:00
parent 455470d018
commit 1b03d41981
3 changed files with 219 additions and 84 deletions

View file

@ -161,7 +161,20 @@ NtEarlyInitVdm(VOID);
__asm__("movl %%cr4,%0\n\t" :"=r" (__d)); \
__d; \
})
#define Ke386SetCr4(X) __asm__("movl %0,%%cr4": :"r" (X));
#define Ke386SetCr4(X) __asm__ __volatile__("movl %0,%%cr4": :"r" (X));
static inline void Ki386Cpuid(ULONG Op, PULONG Eax, PULONG Ebx, PULONG Ecx, PULONG Edx)
{
__asm__("cpuid"
: "=a" (*Eax), "=b" (*Ebx), "=c" (*Ecx), "=d" (*Edx)
: "0" (Op));
}
#define Ke386Rdmsr(msr,val1,val2) __asm__ __volatile__("rdmsr" : "=a" (val1), "=d" (val2) : "c" (msr))
#define Ke386Wrmsr(msr,val1,val2) __asm__ __volatile__("wrmsr" : /* no outputs */ : "c" (msr), "a" (val1), "d" (val2))
#elif defined(_MSC_VER)
#define Ke386DisableInterrupts() __asm cli
#define Ke386EnableInterrupts() __asm sti

View file

@ -38,61 +38,90 @@ static ULONG PcrsAllocated = 0;
static PFN_TYPE PcrPages[MAXIMUM_PROCESSORS];
ULONG Ke386CpuidFlags, Ke386CpuidFlags2, Ke386CpuidExFlags;
ULONG Ke386Cpuid = 0x300;
ULONG Ke386CacheAlignment;
CHAR Ke386CpuidVendor[13] = {0,};
CHAR Ke386CpuidModel[49] = {0,};
ULONG Ke386L1CacheSize;
ULONG Ke386L2CacheSize;
BOOLEAN Ke386NoExecute = FALSE;
BOOLEAN Ke386Pae = FALSE;
/* FUNCTIONS *****************************************************************/
VOID INIT_FUNCTION STATIC
Ki386GetCpuId(VOID)
{
ULONG OrigFlags, Flags, FinalFlags;
ULONG MaxCpuidLevel;
ULONG OrigFlags, Flags, FinalFlags;
ULONG MaxCpuidLevel;
ULONG Dummy, Ebx, Ecx, Edx;
Ke386CpuidFlags = Ke386CpuidFlags2 = Ke386CpuidExFlags = 0;
Ke386CpuidFlags = Ke386CpuidFlags2 = Ke386CpuidExFlags = 0;
Ke386CacheAlignment = 32;
/* Try to toggle the id bit in eflags. */
__asm__ ("pushfl\n\t"
"popl %0\n\t"
: "=r" (OrigFlags));
Flags = OrigFlags ^ X86_EFLAGS_ID;
__asm__ ("pushl %1\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
: "=r" (FinalFlags)
: "r" (Flags));
/* Try to toggle the id bit in eflags. */
__asm__ ("pushfl\n\t"
"popl %0\n\t"
: "=r" (OrigFlags));
Flags = OrigFlags ^ X86_EFLAGS_ID;
__asm__ ("pushl %1\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
: "=r" (FinalFlags)
: "r" (Flags));
if ((OrigFlags & X86_EFLAGS_ID) == (FinalFlags & X86_EFLAGS_ID))
{
{
/* No cpuid supported. */
return;
}
/* Get maximum cpuid level supported. */
__asm__("cpuid\n\t"
: "=a" (MaxCpuidLevel)
: "a" (0x00000000)
: "ebx", "ecx", "edx");
if (MaxCpuidLevel > 0)
{
/* Get the feature flags. */
__asm__("cpuid\n\t"
: "=a" (Ke386Cpuid),"=d" (Ke386CpuidFlags), "=c" (Ke386CpuidFlags2)
: "a" (0x00000001)
: "ebx");
}
}
/* Get the maximum extended cpuid level supported. */
__asm__("cpuid\n\t"
: "=a" (MaxCpuidLevel)
: "a" (0x80000000)
: "ebx", "ecx", "edx");
if (MaxCpuidLevel > 0)
{
/* Get the vendor name and the maximum cpuid level supported. */
Ki386Cpuid(0, &MaxCpuidLevel, (PULONG)&Ke386CpuidVendor[0], (PULONG)&Ke386CpuidVendor[8], (PULONG)&Ke386CpuidVendor[4]);
if (MaxCpuidLevel > 0)
{
/* Get the feature flags. */
Ki386Cpuid(1, &Ke386Cpuid, &Ebx, &Ke386CpuidFlags2, &Ke386CpuidFlags);
/* Get the cache alignment, if it is available */
if (Ke386CpuidFlags & (1<<19))
{
Ke386CacheAlignment = ((Ebx >> 8) & 0xff) * 8;
}
}
/* Get the maximum extended cpuid level supported. */
Ki386Cpuid(0x80000000, &MaxCpuidLevel, &Dummy, &Dummy, &Dummy);
if (MaxCpuidLevel > 0)
{
/* Get the extended feature flags. */
__asm__("cpuid\n\t"
: "=d" (Ke386CpuidExFlags)
: "a" (0x80000001)
: "ebx", "ecx");
}
Ki386Cpuid(0x80000001, &Dummy, &Dummy, &Dummy, &Ke386CpuidExFlags);
}
/* Get the model name. */
if (MaxCpuidLevel >= 0x80000004)
{
PULONG v = (PULONG)&Ke386CpuidModel;
Ki386Cpuid(0x80000002, v, v + 1, v + 2, v + 3);
Ki386Cpuid(0x80000003, v + 4, v + 5, v + 6, v + 7);
Ki386Cpuid(0x80000004, v + 8, v + 9, v + 10, v + 11);
}
/* Get the L1 cache size */
if (MaxCpuidLevel >= 0x80000005)
{
Ki386Cpuid(0x80000005, &Dummy, &Dummy, &Ecx, &Edx);
Ke386L1CacheSize = (Ecx >> 24)+(Edx >> 24);
if ((Ecx & 0xff) > 0)
{
Ke386CacheAlignment = Ecx & 0xff;
}
}
/* Get the L2 cache size */
if (MaxCpuidLevel >= 0x80000006)
{
Ki386Cpuid(0x80000006, &Dummy, &Dummy, &Ecx, &Dummy);
Ke386L2CacheSize = Ecx >> 16;
}
}
VOID INIT_FUNCTION
@ -236,9 +265,34 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
p1 = p2;
}
/*
* FIXME:
* Make the detection of the noexecute feature more portable.
*/
if(((Ke386Cpuid >> 8) & 0xf) == 0xf &&
0 == strcmp("AuthenticAMD", Ke386CpuidVendor))
{
if (NoExecute)
{
ULONG Flags, l, h;
Ke386SaveFlags(Flags);
Ke386DisableInterrupts();
Ke386Rdmsr(0xc0000080, l, h);
l |= (1 << 11);
Ke386Wrmsr(0xc0000080, l, h);
Ke386NoExecute = TRUE;
Ke386RestoreFlags(Flags);
}
}
else
{
NoExecute=FALSE;
}
/* Enable PAE mode */
if ((Pae && (Ke386CpuidFlags & X86_FEATURE_PAE)) ||
(NoExecute && (Ke386CpuidFlags & X86_FEATURE_PAE) /* && (check for the non execution capabilities of the processor) */))
if ((Pae && (Ke386CpuidFlags & X86_FEATURE_PAE)) || NoExecute)
{
MiEnablePAE((PVOID*)LastKernelAddress);
}
@ -255,13 +309,35 @@ KeInit2(VOID)
if (Ke386CpuidFlags & X86_FEATURE_PAE)
{
DPRINT1("CPU supports PAE mode\n");
if (Ke386GetCr4() & X86_CR4_PAE)
if (Ke386Pae)
{
DPRINT1("CPU runs in PAE mode\n");
if (Ke386NoExecute)
{
DPRINT1("NoExecute is enabled\n");
}
}
else
{
DPRINT1("CPU doesn't run in PAE mode\n");
}
}
if (Ke386CpuidVendor[0])
{
DPRINT1("CPU Vendor: %s\n", Ke386CpuidVendor);
}
if (Ke386CpuidModel[0])
{
DPRINT1("CPU Model: %s\n", Ke386CpuidModel);
}
DPRINT1("Ke386CacheAlignment: %d\n", Ke386CacheAlignment);
if (Ke386L1CacheSize)
{
DPRINT1("Ke386L1CacheSize: %dkB\n", Ke386L1CacheSize);
}
if (Ke386L2CacheSize)
{
DPRINT1("Ke386L2CacheSize: %dkB\n", Ke386L2CacheSize);
}
}

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: page.c,v 1.73 2004/09/09 20:42:33 hbirr Exp $
/* $Id: page.c,v 1.74 2004/09/26 16:32:17 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/page.c
@ -78,7 +78,9 @@ __inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage)
#endif
extern ULONG Ke386CpuidFlags;
static BOOLEAN PAE = FALSE;
extern ULONG Ke386Cpuid;
extern BOOLEAN Ke386Pae;
extern BOOLEAN Ke386NoExecute;
/* FUNCTIONS ***************************************************************/
@ -112,7 +114,16 @@ ProtectToPTE(ULONG flProtect)
DPRINT1("Unknown main protection type.\n");
KEBUGCHECK(0);
}
if (!(flProtect & PAGE_SYSTEM))
if (Ke386NoExecute &&
!(flProtect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE)))
{
Attributes = Attributes | 0x80000000;
}
if (flProtect & PAGE_SYSTEM)
{
}
else
{
Attributes = Attributes | PA_USER;
}
@ -172,7 +183,7 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
ExFreePool((PVOID) LdtBase);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG PageDir;
@ -276,7 +287,7 @@ NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest)
DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
if (PAE)
if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG PageDir;
@ -359,7 +370,7 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
KeAttachProcess(Process);
}
if (PAE)
if (Ke386Pae)
{
ULONGLONG ZeroPde = 0LL;
ExfpInterlockedExchange64(PAE_ADDR_TO_PDE(Address), &ZeroPde);
@ -391,7 +402,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
{
KeAttachProcess(Process);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG PageTable;
ULONGLONG ZeroPte = 0LL;
@ -653,7 +664,7 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
BOOLEAN MmUnmapPageTable(PULONG Pt)
{
if (PAE)
if (Ke386Pae)
{
if ((PULONGLONG)Pt >= (PULONGLONG)PAGETABLE_MAP && (PULONGLONG)Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512)
{
@ -709,7 +720,7 @@ MmGetPfnForProcess(PEPROCESS Process,
PVOID Address)
{
if (PAE)
if (Ke386Pae)
{
ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
@ -738,7 +749,7 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PPFN_T
*/
{
BOOLEAN WasValid;
if (PAE)
if (Ke386Pae)
{
ULONGLONG Pte;
ULONGLONG tmpPte;
@ -825,7 +836,7 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PPFN_T
VOID
MmRawDeleteVirtualMapping(PVOID Address)
{
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG ZeroPte = 0LL;
@ -867,7 +878,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
Process, Address, FreePage, WasDirty, Page);
if (PAE)
if (Ke386Pae)
{
ULONGLONG Pte;
PULONGLONG Pt;
@ -994,7 +1005,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
ULONG Idx;
Ptrc = Process->AddressSpace.PageTableRefCountTable;
Idx = PAE ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
Idx = Ke386Pae ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
Ptrc[Idx]--;
if (Ptrc[Idx] == 0)
@ -1011,7 +1022,7 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
* FUNCTION: Delete a virtual mapping
*/
{
if (PAE)
if (Ke386Pae)
{
ULONGLONG Pte;
PULONGLONG Pt;
@ -1110,7 +1121,7 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
{
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
PULONGLONG Pde;
@ -1150,7 +1161,7 @@ Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address)
{
if (PAE)
if (Ke386Pae)
{
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_DIRTY ? TRUE : FALSE;
}
@ -1168,7 +1179,7 @@ MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
KEBUGCHECK(0);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@ -1239,7 +1250,7 @@ VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
DPRINT1("MmSetCleanPage is called for user space without a process.\n");
KEBUGCHECK(0);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@ -1308,7 +1319,7 @@ VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
KEBUGCHECK(0);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@ -1368,7 +1379,7 @@ VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
{
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@ -1428,7 +1439,7 @@ VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
{
if (PAE)
if (Ke386Pae)
{
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_PRESENT ? TRUE : FALSE;
}
@ -1440,7 +1451,7 @@ BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
if (PAE)
if (Ke386Pae)
{
ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
@ -1464,6 +1475,7 @@ MmCreateVirtualMappingForKernel(PVOID Address,
ULONG i;
PVOID Addr;
ULONG PdeOffset, oldPdeOffset;
BOOLEAN NoExecute = FALSE;
DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n",
Address, flProtect, Pages, PageCount);
@ -1475,6 +1487,11 @@ MmCreateVirtualMappingForKernel(PVOID Address,
}
Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Ke386CpuidFlags & X86_FEATURE_PGE)
{
Attributes |= PA_GLOBAL;
@ -1482,7 +1499,7 @@ MmCreateVirtualMappingForKernel(PVOID Address,
Addr = Address;
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt = NULL;
ULONGLONG Pte;
@ -1514,6 +1531,10 @@ MmCreateVirtualMappingForKernel(PVOID Address,
oldPdeOffset = PdeOffset;
Pte = PFN_TO_PTE(Pages[i]) | Attributes;
if (NoExecute)
{
Pte |= 0x8000000000000000LL;
}
Pte = ExfpInterlockedExchange64(Pt, &Pte);
if (Pte != 0LL)
{
@ -1591,7 +1612,7 @@ MmCreatePageFileMapping(PEPROCESS Process,
KEBUGCHECK(0);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@ -1657,7 +1678,7 @@ MmCreatePageFileMapping(PEPROCESS Process,
ULONG Idx;
Ptrc = Process->AddressSpace.PageTableRefCountTable;
Idx = PAE ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
Idx = Ke386Pae ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
Ptrc[Idx]++;
}
return(STATUS_SUCCESS);
@ -1675,9 +1696,10 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
PVOID Addr;
ULONG i;
ULONG oldPdeOffset, PdeOffset;
BOOLEAN NoExecute = FALSE;
DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x, %d)\n",
Process, Address, flProtect, Pages, PageCount);
DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
Process, Address, flProtect, Pages, *Pages, PageCount);
if (Process == NULL)
{
@ -1709,6 +1731,11 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
}
Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Address >= (PVOID)KERNEL_BASE)
{
Attributes &= ~PA_USER;
@ -1724,7 +1751,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
Addr = Address;
if (PAE)
if (Ke386Pae)
{
ULONGLONG Pte, tmpPte;
PULONGLONG Pt = NULL;
@ -1757,6 +1784,10 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
MmMarkPageMapped(Pages[i]);
tmpPte = PAE_PFN_TO_PTE(Pages[i]) | Attributes;
if (NoExecute)
{
tmpPte |= 0x8000000000000000LL;
}
Pte = ExfpInterlockedExchange64(Pt, &tmpPte);
if (PAE_PAGE_MASK((Pte)) != 0LL && !((Pte) & PA_PRESENT))
{
@ -1888,7 +1919,7 @@ MmGetPageProtect(PEPROCESS Process, PVOID Address)
{
ULONG Entry;
ULONG Protect;
if (PAE)
if (Ke386Pae)
{
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
}
@ -1932,11 +1963,17 @@ VOID
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{
ULONG Attributes = 0;
BOOLEAN NoExecute = FALSE;
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
Process, Address, flProtect);
Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Address >= (PVOID)KERNEL_BASE)
{
Attributes &= ~PA_USER;
@ -1949,7 +1986,7 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{
Attributes |= PA_USER;
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG tmpPte, Pte;
@ -1957,12 +1994,21 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL)
{
DPRINT1("Address %x\n", Address);
KEBUGCHECK(0);
}
do
{
Pte = *Pt;
tmpPte = PAE_PAGE_MASK(Pte) | Attributes | (Pte & (PA_ACCESSED|PA_DIRTY));
if (NoExecute)
{
tmpPte |= 0x8000000000000000LL;
}
else
{
tmpPte &= ~0x8000000000000000LL;
}
} while (Pte != ExfInterlockedCompareExchange64(Pt, &tmpPte, &Pte));
if (MmUnmapPageTable((PULONG)Pt) || Address > (PVOID)KERNEL_BASE)
@ -1999,7 +2045,7 @@ MmGetPhysicalAddress(PVOID vaddr)
PHYSICAL_ADDRESS p;
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
if (PAE)
if (Ke386Pae)
{
ULONGLONG Pte;
Pte = MmGetPageEntryForProcessForPAE(NULL, vaddr);
@ -2038,7 +2084,7 @@ VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size)
{
KEBUGCHECK(0);
}
if (PAE)
if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG Pde;
@ -2098,7 +2144,7 @@ VOID INIT_FUNCTION
MmInitGlobalKernelPageDirectory(VOID)
{
ULONG i;
if (PAE)
if (Ke386Pae)
{
PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP + 3*512;
for (i = 0; i < 512; i++)
@ -2198,7 +2244,7 @@ MiEnablePAE(PVOID* LastKernelAddress)
else
{
/* this is an application processor in a mp system */
if (PAE == FALSE)
if (!Ke386Pae)
{
return;
}
@ -2212,7 +2258,7 @@ MiEnablePAE(PVOID* LastKernelAddress)
Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE);
if (LastKernelAddress)
{
PAE = TRUE;
Ke386Pae = TRUE;
}
Ke386RestoreFlags(Flags);
}
@ -2220,7 +2266,7 @@ MiEnablePAE(PVOID* LastKernelAddress)
ULONG
MiGetUserPageDirectoryCount(VOID)
{
return PAE ? 1536 : 768;
return Ke386Pae ? 1536 : 768;
}
VOID INIT_FUNCTION
@ -2231,12 +2277,12 @@ MiInitPageDirectoryMap(VOID)
PVOID BaseAddress;
BoundaryAddressMultiple.QuadPart = 0;
BaseAddress = (PVOID)0xf0000000;
BaseAddress = (PVOID)PAGETABLE_MAP;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
PAE ? 0x800000 : 0x400000,
Ke386Pae ? 0x800000 : 0x400000,
0,
&kernel_map_desc,
TRUE,