reactos/ntoskrnl/mm/i386
diff -u -r1.73 -r1.74
--- page.c 9 Sep 2004 20:42:33 -0000 1.73
+++ page.c 26 Sep 2004 16:32:17 -0000 1.74
@@ -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 @@
#endif
extern ULONG Ke386CpuidFlags;
-static BOOLEAN PAE = FALSE;
+extern ULONG Ke386Cpuid;
+extern BOOLEAN Ke386Pae;
+extern BOOLEAN Ke386NoExecute;
/* FUNCTIONS ***************************************************************/
@@ -112,7 +114,16 @@
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 @@
ExFreePool((PVOID) LdtBase);
}
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG PageDir;
@@ -276,7 +287,7 @@
DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG PageDir;
@@ -359,7 +370,7 @@
KeAttachProcess(Process);
}
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG ZeroPde = 0LL;
ExfpInterlockedExchange64(PAE_ADDR_TO_PDE(Address), &ZeroPde);
@@ -391,7 +402,7 @@
{
KeAttachProcess(Process);
}
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG PageTable;
ULONGLONG ZeroPte = 0LL;
@@ -653,7 +664,7 @@
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 @@
PVOID Address)
{
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
@@ -738,7 +749,7 @@
*/
{
BOOLEAN WasValid;
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG Pte;
ULONGLONG tmpPte;
@@ -825,7 +836,7 @@
VOID
MmRawDeleteVirtualMapping(PVOID Address)
{
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG ZeroPte = 0LL;
@@ -867,7 +878,7 @@
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 @@
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 @@
* FUNCTION: Delete a virtual mapping
*/
{
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG Pte;
PULONGLONG Pt;
@@ -1110,7 +1121,7 @@
BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
{
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG Pt;
PULONGLONG Pde;
@@ -1150,7 +1161,7 @@
BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address)
{
- if (PAE)
+ if (Ke386Pae)
{
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_DIRTY ? TRUE : FALSE;
}
@@ -1168,7 +1179,7 @@
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 @@
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 @@
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 MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
{
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@@ -1428,7 +1439,7 @@
BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
{
- if (PAE)
+ if (Ke386Pae)
{
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_PRESENT ? TRUE : FALSE;
}
@@ -1440,7 +1451,7 @@
BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG Entry;
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
@@ -1464,6 +1475,7 @@
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 @@
}
Attributes = ProtectToPTE(flProtect);
+ if (Attributes & 0x80000000)
+ {
+ NoExecute = TRUE;
+ }
+ Attributes &= 0xfff;
if (Ke386CpuidFlags & X86_FEATURE_PGE)
{
Attributes |= PA_GLOBAL;
@@ -1482,7 +1499,7 @@
Addr = Address;
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG Pt = NULL;
ULONGLONG Pte;
@@ -1514,6 +1531,10 @@
oldPdeOffset = PdeOffset;
Pte = PFN_TO_PTE(Pages[i]) | Attributes;
+ if (NoExecute)
+ {
+ Pte |= 0x8000000000000000LL;
+ }
Pte = ExfpInterlockedExchange64(Pt, &Pte);
if (Pte != 0LL)
{
@@ -1591,7 +1612,7 @@
KEBUGCHECK(0);
}
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG Pte;
@@ -1657,7 +1678,7 @@
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 @@
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 @@
}
Attributes = ProtectToPTE(flProtect);
+ if (Attributes & 0x80000000)
+ {
+ NoExecute = TRUE;
+ }
+ Attributes &= 0xfff;
if (Address >= (PVOID)KERNEL_BASE)
{
Attributes &= ~PA_USER;
@@ -1724,7 +1751,7 @@
Addr = Address;
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG Pte, tmpPte;
PULONGLONG Pt = NULL;
@@ -1757,6 +1784,10 @@
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 @@
{
ULONG Entry;
ULONG Protect;
- if (PAE)
+ if (Ke386Pae)
{
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
}
@@ -1932,11 +1963,17 @@
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 @@
{
Attributes |= PA_USER;
}
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG Pt;
ULONGLONG tmpPte, Pte;
@@ -1957,12 +1994,21 @@
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 @@
PHYSICAL_ADDRESS p;
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
- if (PAE)
+ if (Ke386Pae)
{
ULONGLONG Pte;
Pte = MmGetPageEntryForProcessForPAE(NULL, vaddr);
@@ -2038,7 +2084,7 @@
{
KEBUGCHECK(0);
}
- if (PAE)
+ if (Ke386Pae)
{
PULONGLONG PageDirTable;
PULONGLONG Pde;
@@ -2098,7 +2144,7 @@
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 @@
else
{
/* this is an application processor in a mp system */
- if (PAE == FALSE)
+ if (!Ke386Pae)
{
return;
}
@@ -2212,7 +2258,7 @@
Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE);
if (LastKernelAddress)
{
- PAE = TRUE;
+ Ke386Pae = TRUE;
}
Ke386RestoreFlags(Flags);
}
@@ -2220,7 +2266,7 @@
ULONG
MiGetUserPageDirectoryCount(VOID)
{
- return PAE ? 1536 : 768;
+ return Ke386Pae ? 1536 : 768;
}
VOID INIT_FUNCTION
@@ -2231,12 +2277,12 @@
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,
reactos/ntoskrnl/ke/i386
diff -u -r1.32 -r1.33
--- kernel.c 9 Sep 2004 20:42:33 -0000 1.32
+++ kernel.c 26 Sep 2004 16:32:18 -0000 1.33
@@ -38,61 +38,90 @@
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;
-
- Ke386CpuidFlags = Ke386CpuidFlags2 = Ke386CpuidExFlags = 0;
-
- /* 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));
+ ULONG OrigFlags, Flags, FinalFlags;
+ ULONG MaxCpuidLevel;
+ ULONG Dummy, Ebx, Ecx, Edx;
+
+ 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));
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 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. */
- __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)
- {
+ 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 @@
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 @@
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);
+ }
}