- 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)); \ __asm__("movl %%cr4,%0\n\t" :"=r" (__d)); \
__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) #elif defined(_MSC_VER)
#define Ke386DisableInterrupts() __asm cli #define Ke386DisableInterrupts() __asm cli
#define Ke386EnableInterrupts() __asm sti #define Ke386EnableInterrupts() __asm sti

View file

@ -38,61 +38,90 @@ static ULONG PcrsAllocated = 0;
static PFN_TYPE PcrPages[MAXIMUM_PROCESSORS]; static PFN_TYPE PcrPages[MAXIMUM_PROCESSORS];
ULONG Ke386CpuidFlags, Ke386CpuidFlags2, Ke386CpuidExFlags; ULONG Ke386CpuidFlags, Ke386CpuidFlags2, Ke386CpuidExFlags;
ULONG Ke386Cpuid = 0x300; ULONG Ke386Cpuid = 0x300;
ULONG Ke386CacheAlignment;
CHAR Ke386CpuidVendor[13] = {0,};
CHAR Ke386CpuidModel[49] = {0,};
ULONG Ke386L1CacheSize;
ULONG Ke386L2CacheSize;
BOOLEAN Ke386NoExecute = FALSE;
BOOLEAN Ke386Pae = FALSE;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID INIT_FUNCTION STATIC VOID INIT_FUNCTION STATIC
Ki386GetCpuId(VOID) Ki386GetCpuId(VOID)
{ {
ULONG OrigFlags, Flags, FinalFlags; ULONG OrigFlags, Flags, FinalFlags;
ULONG MaxCpuidLevel; 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. */ /* Try to toggle the id bit in eflags. */
__asm__ ("pushfl\n\t" __asm__ ("pushfl\n\t"
"popl %0\n\t" "popl %0\n\t"
: "=r" (OrigFlags)); : "=r" (OrigFlags));
Flags = OrigFlags ^ X86_EFLAGS_ID; Flags = OrigFlags ^ X86_EFLAGS_ID;
__asm__ ("pushl %1\n\t" __asm__ ("pushl %1\n\t"
"popfl\n\t" "popfl\n\t"
"pushfl\n\t" "pushfl\n\t"
"popl %0\n\t" "popl %0\n\t"
: "=r" (FinalFlags) : "=r" (FinalFlags)
: "r" (Flags)); : "r" (Flags));
if ((OrigFlags & X86_EFLAGS_ID) == (FinalFlags & X86_EFLAGS_ID)) if ((OrigFlags & X86_EFLAGS_ID) == (FinalFlags & X86_EFLAGS_ID))
{ {
/* No cpuid supported. */ /* No cpuid supported. */
return; return;
} }
/* Get maximum cpuid level supported. */ /* Get the vendor name and the maximum cpuid level supported. */
__asm__("cpuid\n\t" Ki386Cpuid(0, &MaxCpuidLevel, (PULONG)&Ke386CpuidVendor[0], (PULONG)&Ke386CpuidVendor[8], (PULONG)&Ke386CpuidVendor[4]);
: "=a" (MaxCpuidLevel) if (MaxCpuidLevel > 0)
: "a" (0x00000000) {
: "ebx", "ecx", "edx");
if (MaxCpuidLevel > 0)
{
/* Get the feature flags. */ /* Get the feature flags. */
__asm__("cpuid\n\t" Ki386Cpuid(1, &Ke386Cpuid, &Ebx, &Ke386CpuidFlags2, &Ke386CpuidFlags);
: "=a" (Ke386Cpuid),"=d" (Ke386CpuidFlags), "=c" (Ke386CpuidFlags2) /* Get the cache alignment, if it is available */
: "a" (0x00000001) if (Ke386CpuidFlags & (1<<19))
: "ebx"); {
} Ke386CacheAlignment = ((Ebx >> 8) & 0xff) * 8;
}
}
/* Get the maximum extended cpuid level supported. */ /* Get the maximum extended cpuid level supported. */
__asm__("cpuid\n\t" Ki386Cpuid(0x80000000, &MaxCpuidLevel, &Dummy, &Dummy, &Dummy);
: "=a" (MaxCpuidLevel) if (MaxCpuidLevel > 0)
: "a" (0x80000000) {
: "ebx", "ecx", "edx");
if (MaxCpuidLevel > 0)
{
/* Get the extended feature flags. */ /* Get the extended feature flags. */
__asm__("cpuid\n\t" Ki386Cpuid(0x80000001, &Dummy, &Dummy, &Dummy, &Ke386CpuidExFlags);
: "=d" (Ke386CpuidExFlags) }
: "a" (0x80000001)
: "ebx", "ecx"); /* 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 VOID INIT_FUNCTION
@ -236,9 +265,34 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
p1 = p2; 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 */ /* Enable PAE mode */
if ((Pae && (Ke386CpuidFlags & X86_FEATURE_PAE)) || if ((Pae && (Ke386CpuidFlags & X86_FEATURE_PAE)) || NoExecute)
(NoExecute && (Ke386CpuidFlags & X86_FEATURE_PAE) /* && (check for the non execution capabilities of the processor) */))
{ {
MiEnablePAE((PVOID*)LastKernelAddress); MiEnablePAE((PVOID*)LastKernelAddress);
} }
@ -255,13 +309,35 @@ KeInit2(VOID)
if (Ke386CpuidFlags & X86_FEATURE_PAE) if (Ke386CpuidFlags & X86_FEATURE_PAE)
{ {
DPRINT1("CPU supports PAE mode\n"); DPRINT1("CPU supports PAE mode\n");
if (Ke386GetCr4() & X86_CR4_PAE) if (Ke386Pae)
{ {
DPRINT1("CPU runs in PAE mode\n"); DPRINT1("CPU runs in PAE mode\n");
if (Ke386NoExecute)
{
DPRINT1("NoExecute is enabled\n");
}
} }
else else
{ {
DPRINT1("CPU doesn't run in PAE mode\n"); 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 * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/page.c * FILE: ntoskrnl/mm/i386/page.c
@ -78,7 +78,9 @@ __inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage)
#endif #endif
extern ULONG Ke386CpuidFlags; extern ULONG Ke386CpuidFlags;
static BOOLEAN PAE = FALSE; extern ULONG Ke386Cpuid;
extern BOOLEAN Ke386Pae;
extern BOOLEAN Ke386NoExecute;
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
@ -112,7 +114,16 @@ ProtectToPTE(ULONG flProtect)
DPRINT1("Unknown main protection type.\n"); DPRINT1("Unknown main protection type.\n");
KEBUGCHECK(0); 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; Attributes = Attributes | PA_USER;
} }
@ -172,7 +183,7 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
ExFreePool((PVOID) LdtBase); ExFreePool((PVOID) LdtBase);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG PageDirTable; PULONGLONG PageDirTable;
PULONGLONG PageDir; PULONGLONG PageDir;
@ -276,7 +287,7 @@ NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest)
DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest); DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
if (PAE) if (Ke386Pae)
{ {
PULONGLONG PageDirTable; PULONGLONG PageDirTable;
PULONGLONG PageDir; PULONGLONG PageDir;
@ -359,7 +370,7 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
KeAttachProcess(Process); KeAttachProcess(Process);
} }
if (PAE) if (Ke386Pae)
{ {
ULONGLONG ZeroPde = 0LL; ULONGLONG ZeroPde = 0LL;
ExfpInterlockedExchange64(PAE_ADDR_TO_PDE(Address), &ZeroPde); ExfpInterlockedExchange64(PAE_ADDR_TO_PDE(Address), &ZeroPde);
@ -391,7 +402,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
{ {
KeAttachProcess(Process); KeAttachProcess(Process);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG PageTable; PULONGLONG PageTable;
ULONGLONG ZeroPte = 0LL; ULONGLONG ZeroPte = 0LL;
@ -653,7 +664,7 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
BOOLEAN MmUnmapPageTable(PULONG Pt) BOOLEAN MmUnmapPageTable(PULONG Pt)
{ {
if (PAE) if (Ke386Pae)
{ {
if ((PULONGLONG)Pt >= (PULONGLONG)PAGETABLE_MAP && (PULONGLONG)Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512) if ((PULONGLONG)Pt >= (PULONGLONG)PAGETABLE_MAP && (PULONGLONG)Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512)
{ {
@ -709,7 +720,7 @@ MmGetPfnForProcess(PEPROCESS Process,
PVOID Address) PVOID Address)
{ {
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Entry; ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address); Entry = MmGetPageEntryForProcessForPAE(Process, Address);
@ -738,7 +749,7 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PPFN_T
*/ */
{ {
BOOLEAN WasValid; BOOLEAN WasValid;
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Pte; ULONGLONG Pte;
ULONGLONG tmpPte; ULONGLONG tmpPte;
@ -825,7 +836,7 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PPFN_T
VOID VOID
MmRawDeleteVirtualMapping(PVOID Address) MmRawDeleteVirtualMapping(PVOID Address)
{ {
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG ZeroPte = 0LL; ULONGLONG ZeroPte = 0LL;
@ -867,7 +878,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n", DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
Process, Address, FreePage, WasDirty, Page); Process, Address, FreePage, WasDirty, Page);
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Pte; ULONGLONG Pte;
PULONGLONG Pt; PULONGLONG Pt;
@ -994,7 +1005,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
ULONG Idx; ULONG Idx;
Ptrc = Process->AddressSpace.PageTableRefCountTable; 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]--; Ptrc[Idx]--;
if (Ptrc[Idx] == 0) if (Ptrc[Idx] == 0)
@ -1011,7 +1022,7 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
* FUNCTION: Delete a virtual mapping * FUNCTION: Delete a virtual mapping
*/ */
{ {
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Pte; ULONGLONG Pte;
PULONGLONG Pt; PULONGLONG Pt;
@ -1110,7 +1121,7 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
BOOLEAN BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID PAddress) Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
{ {
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
PULONGLONG Pde; PULONGLONG Pde;
@ -1150,7 +1161,7 @@ Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address) BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address)
{ {
if (PAE) if (Ke386Pae)
{ {
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_DIRTY ? TRUE : FALSE; 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"); DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
KEBUGCHECK(0); KEBUGCHECK(0);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG Pte; ULONGLONG Pte;
@ -1239,7 +1250,7 @@ VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
DPRINT1("MmSetCleanPage is called for user space without a process.\n"); DPRINT1("MmSetCleanPage is called for user space without a process.\n");
KEBUGCHECK(0); KEBUGCHECK(0);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG Pte; ULONGLONG Pte;
@ -1308,7 +1319,7 @@ VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
DPRINT1("MmSetDirtyPage is called for user space without a process.\n"); DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
KEBUGCHECK(0); KEBUGCHECK(0);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG Pte; ULONGLONG Pte;
@ -1368,7 +1379,7 @@ VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address) VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
{ {
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG Pte; ULONGLONG Pte;
@ -1428,7 +1439,7 @@ VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address) BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
{ {
if (PAE) if (Ke386Pae)
{ {
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_PRESENT ? TRUE : FALSE; return MmGetPageEntryForProcessForPAE(Process, Address) & PA_PRESENT ? TRUE : FALSE;
} }
@ -1440,7 +1451,7 @@ BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{ {
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Entry; ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address); Entry = MmGetPageEntryForProcessForPAE(Process, Address);
@ -1464,6 +1475,7 @@ MmCreateVirtualMappingForKernel(PVOID Address,
ULONG i; ULONG i;
PVOID Addr; PVOID Addr;
ULONG PdeOffset, oldPdeOffset; ULONG PdeOffset, oldPdeOffset;
BOOLEAN NoExecute = FALSE;
DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n", DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n",
Address, flProtect, Pages, PageCount); Address, flProtect, Pages, PageCount);
@ -1475,6 +1487,11 @@ MmCreateVirtualMappingForKernel(PVOID Address,
} }
Attributes = ProtectToPTE(flProtect); Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Ke386CpuidFlags & X86_FEATURE_PGE) if (Ke386CpuidFlags & X86_FEATURE_PGE)
{ {
Attributes |= PA_GLOBAL; Attributes |= PA_GLOBAL;
@ -1482,7 +1499,7 @@ MmCreateVirtualMappingForKernel(PVOID Address,
Addr = Address; Addr = Address;
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt = NULL; PULONGLONG Pt = NULL;
ULONGLONG Pte; ULONGLONG Pte;
@ -1514,6 +1531,10 @@ MmCreateVirtualMappingForKernel(PVOID Address,
oldPdeOffset = PdeOffset; oldPdeOffset = PdeOffset;
Pte = PFN_TO_PTE(Pages[i]) | Attributes; Pte = PFN_TO_PTE(Pages[i]) | Attributes;
if (NoExecute)
{
Pte |= 0x8000000000000000LL;
}
Pte = ExfpInterlockedExchange64(Pt, &Pte); Pte = ExfpInterlockedExchange64(Pt, &Pte);
if (Pte != 0LL) if (Pte != 0LL)
{ {
@ -1591,7 +1612,7 @@ MmCreatePageFileMapping(PEPROCESS Process,
KEBUGCHECK(0); KEBUGCHECK(0);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG Pte; ULONGLONG Pte;
@ -1657,7 +1678,7 @@ MmCreatePageFileMapping(PEPROCESS Process,
ULONG Idx; ULONG Idx;
Ptrc = Process->AddressSpace.PageTableRefCountTable; 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]++; Ptrc[Idx]++;
} }
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -1675,9 +1696,10 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
PVOID Addr; PVOID Addr;
ULONG i; ULONG i;
ULONG oldPdeOffset, PdeOffset; ULONG oldPdeOffset, PdeOffset;
BOOLEAN NoExecute = FALSE;
DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x, %d)\n", DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
Process, Address, flProtect, Pages, PageCount); Process, Address, flProtect, Pages, *Pages, PageCount);
if (Process == NULL) if (Process == NULL)
{ {
@ -1709,6 +1731,11 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
} }
Attributes = ProtectToPTE(flProtect); Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Address >= (PVOID)KERNEL_BASE) if (Address >= (PVOID)KERNEL_BASE)
{ {
Attributes &= ~PA_USER; Attributes &= ~PA_USER;
@ -1724,7 +1751,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
Addr = Address; Addr = Address;
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Pte, tmpPte; ULONGLONG Pte, tmpPte;
PULONGLONG Pt = NULL; PULONGLONG Pt = NULL;
@ -1757,6 +1784,10 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
MmMarkPageMapped(Pages[i]); MmMarkPageMapped(Pages[i]);
tmpPte = PAE_PFN_TO_PTE(Pages[i]) | Attributes; tmpPte = PAE_PFN_TO_PTE(Pages[i]) | Attributes;
if (NoExecute)
{
tmpPte |= 0x8000000000000000LL;
}
Pte = ExfpInterlockedExchange64(Pt, &tmpPte); Pte = ExfpInterlockedExchange64(Pt, &tmpPte);
if (PAE_PAGE_MASK((Pte)) != 0LL && !((Pte) & PA_PRESENT)) if (PAE_PAGE_MASK((Pte)) != 0LL && !((Pte) & PA_PRESENT))
{ {
@ -1888,7 +1919,7 @@ MmGetPageProtect(PEPROCESS Process, PVOID Address)
{ {
ULONG Entry; ULONG Entry;
ULONG Protect; ULONG Protect;
if (PAE) if (Ke386Pae)
{ {
Entry = MmGetPageEntryForProcessForPAE(Process, Address); Entry = MmGetPageEntryForProcessForPAE(Process, Address);
} }
@ -1932,11 +1963,17 @@ VOID
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{ {
ULONG Attributes = 0; ULONG Attributes = 0;
BOOLEAN NoExecute = FALSE;
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n", DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
Process, Address, flProtect); Process, Address, flProtect);
Attributes = ProtectToPTE(flProtect); Attributes = ProtectToPTE(flProtect);
if (Attributes & 0x80000000)
{
NoExecute = TRUE;
}
Attributes &= 0xfff;
if (Address >= (PVOID)KERNEL_BASE) if (Address >= (PVOID)KERNEL_BASE)
{ {
Attributes &= ~PA_USER; Attributes &= ~PA_USER;
@ -1949,7 +1986,7 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{ {
Attributes |= PA_USER; Attributes |= PA_USER;
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG Pt; PULONGLONG Pt;
ULONGLONG tmpPte, Pte; ULONGLONG tmpPte, Pte;
@ -1957,12 +1994,21 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE); Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
if (Pt == NULL) if (Pt == NULL)
{ {
DPRINT1("Address %x\n", Address);
KEBUGCHECK(0); KEBUGCHECK(0);
} }
do do
{ {
Pte = *Pt; Pte = *Pt;
tmpPte = PAE_PAGE_MASK(Pte) | Attributes | (Pte & (PA_ACCESSED|PA_DIRTY)); tmpPte = PAE_PAGE_MASK(Pte) | Attributes | (Pte & (PA_ACCESSED|PA_DIRTY));
if (NoExecute)
{
tmpPte |= 0x8000000000000000LL;
}
else
{
tmpPte &= ~0x8000000000000000LL;
}
} while (Pte != ExfInterlockedCompareExchange64(Pt, &tmpPte, &Pte)); } while (Pte != ExfInterlockedCompareExchange64(Pt, &tmpPte, &Pte));
if (MmUnmapPageTable((PULONG)Pt) || Address > (PVOID)KERNEL_BASE) if (MmUnmapPageTable((PULONG)Pt) || Address > (PVOID)KERNEL_BASE)
@ -1999,7 +2045,7 @@ MmGetPhysicalAddress(PVOID vaddr)
PHYSICAL_ADDRESS p; PHYSICAL_ADDRESS p;
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr); DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
if (PAE) if (Ke386Pae)
{ {
ULONGLONG Pte; ULONGLONG Pte;
Pte = MmGetPageEntryForProcessForPAE(NULL, vaddr); Pte = MmGetPageEntryForProcessForPAE(NULL, vaddr);
@ -2038,7 +2084,7 @@ VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size)
{ {
KEBUGCHECK(0); KEBUGCHECK(0);
} }
if (PAE) if (Ke386Pae)
{ {
PULONGLONG PageDirTable; PULONGLONG PageDirTable;
PULONGLONG Pde; PULONGLONG Pde;
@ -2098,7 +2144,7 @@ VOID INIT_FUNCTION
MmInitGlobalKernelPageDirectory(VOID) MmInitGlobalKernelPageDirectory(VOID)
{ {
ULONG i; ULONG i;
if (PAE) if (Ke386Pae)
{ {
PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP + 3*512; PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP + 3*512;
for (i = 0; i < 512; i++) for (i = 0; i < 512; i++)
@ -2198,7 +2244,7 @@ MiEnablePAE(PVOID* LastKernelAddress)
else else
{ {
/* this is an application processor in a mp system */ /* this is an application processor in a mp system */
if (PAE == FALSE) if (!Ke386Pae)
{ {
return; return;
} }
@ -2212,7 +2258,7 @@ MiEnablePAE(PVOID* LastKernelAddress)
Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE); Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE);
if (LastKernelAddress) if (LastKernelAddress)
{ {
PAE = TRUE; Ke386Pae = TRUE;
} }
Ke386RestoreFlags(Flags); Ke386RestoreFlags(Flags);
} }
@ -2220,7 +2266,7 @@ MiEnablePAE(PVOID* LastKernelAddress)
ULONG ULONG
MiGetUserPageDirectoryCount(VOID) MiGetUserPageDirectoryCount(VOID)
{ {
return PAE ? 1536 : 768; return Ke386Pae ? 1536 : 768;
} }
VOID INIT_FUNCTION VOID INIT_FUNCTION
@ -2231,12 +2277,12 @@ MiInitPageDirectoryMap(VOID)
PVOID BaseAddress; PVOID BaseAddress;
BoundaryAddressMultiple.QuadPart = 0; BoundaryAddressMultiple.QuadPart = 0;
BaseAddress = (PVOID)0xf0000000; BaseAddress = (PVOID)PAGETABLE_MAP;
MmCreateMemoryArea(NULL, MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(), MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM, MEMORY_AREA_SYSTEM,
&BaseAddress, &BaseAddress,
PAE ? 0x800000 : 0x400000, Ke386Pae ? 0x800000 : 0x400000,
0, 0,
&kernel_map_desc, &kernel_map_desc,
TRUE, TRUE,