From 5e026edfdc112f675536effe62347a73062a3cb4 Mon Sep 17 00:00:00 2001 From: Stefan Ginsberg Date: Wed, 14 Oct 2015 19:33:35 +0000 Subject: [PATCH] [NTOS] Add super-complicated handling of global pages to KeFlushCurrentTb (pretty much the same code which has been in HalpFlushTLB for the past ~6 years). This should be all that is required to make this feature work (everything else being in place already), and *seems* to work fine but is disabled under a switch until tested thoroughly. Global pages, an important optimization that allows for not flushing the whole x86 TLB every time CR3 is changed (typically on context switch to a new process, or during process attach/detach), relies on us doing extra work whenever we do alter a global page. This is likely where any bugs will have to be flushed out! Fixup Ki386EnableGlobalPage while we are at it -- disable/restore interrupts properly, and verify PGE-bit isn't set (nothing should have touched it before this routine, which is responsible for initializing it, so we shouldn't have to disable it). Fix, but disable, the CPU-sync spin as well as there should be no particular reason to do this for PGE-enabling during initialization (no other processor will be messing with PTEs at this stage, as compared to a call to KeFlushEntireTb). Everyone, repeat after me: Global pages are awesome! svn path=/trunk/; revision=69528 --- reactos/ntoskrnl/include/ntoskrnl.h | 8 ++++++ reactos/ntoskrnl/ke/i386/cpu.c | 29 ++++++++++++++++++++ reactos/ntoskrnl/ke/i386/patpge.c | 41 ++++++++++++++-------------- reactos/ntoskrnl/mm/ARM3/i386/init.c | 5 +++- 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/reactos/ntoskrnl/include/ntoskrnl.h b/reactos/ntoskrnl/include/ntoskrnl.h index 404878ad00d..400a153ccc9 100644 --- a/reactos/ntoskrnl/include/ntoskrnl.h +++ b/reactos/ntoskrnl/include/ntoskrnl.h @@ -98,6 +98,14 @@ #define ASSERT NT_ASSERT #endif + +// +// Switch for enabling global page support +// + +//#define _GLOBAL_PAGES_ARE_AWESOME_ + + /* Internal Headers */ #include "internal/ntoskrnl.h" #include "config.h" diff --git a/reactos/ntoskrnl/ke/i386/cpu.c b/reactos/ntoskrnl/ke/i386/cpu.c index c9ca0cda244..3d4ea82d9b8 100644 --- a/reactos/ntoskrnl/ke/i386/cpu.c +++ b/reactos/ntoskrnl/ke/i386/cpu.c @@ -878,8 +878,37 @@ VOID NTAPI KeFlushCurrentTb(VOID) { + +#if !defined(_GLOBAL_PAGES_ARE_AWESOME_) + /* Flush the TLB by resetting CR3 */ __writecr3(__readcr3()); + +#else + + /* Check if global pages are enabled */ + if (KeFeatureBits & KF_GLOBAL_PAGE) + { + ULONG Cr4; + + /* Disable PGE */ + Cr4 = __readcr4() & ~CR4_PGE; + __writecr4(Cr4); + + /* Flush everything */ + __writecr3(__readcr3()); + + /* Re-enable PGE */ + __writecr4(Cr4 | CR4_PGE); + } + else + { + /* No global pages, resetting CR3 is enough */ + __writecr3(__readcr3()); + } + +#endif + } VOID diff --git a/reactos/ntoskrnl/ke/i386/patpge.c b/reactos/ntoskrnl/ke/i386/patpge.c index 1e598ce355a..a0e9b494240 100644 --- a/reactos/ntoskrnl/ke/i386/patpge.c +++ b/reactos/ntoskrnl/ke/i386/patpge.c @@ -17,40 +17,41 @@ /* FUNCTIONS *****************************************************************/ +INIT_SECTION ULONG_PTR NTAPI -INIT_FUNCTION Ki386EnableGlobalPage(IN ULONG_PTR Context) { - PLONG Count = (PLONG)Context; - ULONG Cr4, Cr3; + //PLONG Count; +#if defined(_GLOBAL_PAGES_ARE_AWESOME_) + ULONG Cr4; +#endif + BOOLEAN Enable; /* Disable interrupts */ - _disable(); + Enable = KeDisableInterrupts(); - /* Decrease CPU Count and loop until it's reached 0 */ - do {InterlockedDecrement(Count);} while (!*Count); + /* Spin until other processors are ready */ + //Count = (PLONG)Context; + //InterlockedDecrement(Count); + //while (*Count) YieldProcessor(); - /* Now check if this is the Boot CPU */ - if (!KeGetPcr()->Number) - { - /* It is.FIXME: Patch KeFlushCurrentTb */ - } +#if defined(_GLOBAL_PAGES_ARE_AWESOME_) - /* Now get CR4 and make sure PGE is masked out */ + /* Get CR4 and ensure global pages are disabled */ Cr4 = __readcr4(); - __writecr4(Cr4 & ~CR4_PGE); + ASSERT(!(Cr4 & CR4_PGE)); - /* Flush the TLB */ - Cr3 = __readcr3(); - __writecr3(Cr3); + /* Reset CR3 to flush the TLB */ + __writecr3(__readcr3()); /* Now enable PGE */ - DPRINT("Global page support detected but not yet taken advantage of\n"); - //__writecr4(Cr4 | CR4_PGE); + __writecr4(Cr4 | CR4_PGE); - /* Restore interrupts */ - _enable(); +#endif + + /* Restore interrupts and return */ + KeRestoreInterrupts(Enable); return 0; } diff --git a/reactos/ntoskrnl/mm/ARM3/i386/init.c b/reactos/ntoskrnl/mm/ARM3/i386/init.c index c5c6bb308ba..5a42219302d 100644 --- a/reactos/ntoskrnl/mm/ARM3/i386/init.c +++ b/reactos/ntoskrnl/mm/ARM3/i386/init.c @@ -249,15 +249,18 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) PMMPFN Pfn1; ULONG Flags; +#if defined(_GLOBAL_PAGES_ARE_AWESOME_) + /* Check for global bit */ -#if 0 if (KeFeatureBits & KF_GLOBAL_PAGE) { /* Set it on the template PTE and PDE */ ValidKernelPte.u.Hard.Global = TRUE; ValidKernelPde.u.Hard.Global = TRUE; } + #endif + /* Now templates are ready */ TempPte = ValidKernelPte; TempPde = ValidKernelPde;