-
-
Notifications
You must be signed in to change notification settings - Fork 2k
[NTOS] Implement support for global pages #7937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
08ad46a
35edb85
c3d0f1b
d02b648
d4cfb8c
12d75df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| #pragma once | ||
|
|
||
| // Enable global page support. | ||
| // #define _GLOBAL_PAGES_ARE_AWESOME_ | ||
| #define _GLOBAL_PAGES_ARE_AWESOME_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| /* | ||
| * PROJECT: ReactOS Kernel | ||
| * LICENSE: MIT (https://spdx.org/licenses/MIT) | ||
| * PURPOSE: Architecture specific support routines shared between x86 and x64 | ||
| * COPYRIGHT: Copyright 2025 Timo Kreuzer <[email protected]> | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| extern ULONG64 KeFeatureBits; | ||
|
|
||
| static const ULONG KxFlushIndividualProcessPagesMaximum = 33; // Based on Linux tlb_single_page_flush_ceiling | ||
| static const ULONG KxFlushIndividualGlobalPagesMaximum = 100; // Just a guess | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are these variables for? Some sort of arbitrary threshold that when reached in KeFlushRangeTb and friends, a full flush is done? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Use the source, Luke. |
||
|
|
||
| /*! | ||
| * \brief Flushes the current processor's TLB for a single page. | ||
| * \note This function flushes global pages. | ||
| */ | ||
| FORCEINLINE | ||
| VOID | ||
| KxFlushSingleCurrentTb( | ||
| _In_ PVOID Address) | ||
| { | ||
| /* Invalidate the TLB entry for this address */ | ||
| __invlpg(Address); | ||
| } | ||
|
|
||
| /*! | ||
| * \brief Flushes the current processor's TLB for a range of pages. | ||
| * \param Address The starting address of the range to flush. | ||
| * \param NumberOfPages The number of pages to flush. | ||
| * \note This function flushes global pages. It does not optimize for large ranges. | ||
| */ | ||
| FORCEINLINE | ||
| VOID | ||
| KxFlushRangeCurrentTb( | ||
| _In_ PVOID Address, | ||
| _In_ ULONG NumberOfPages) | ||
| { | ||
| /* Invalidate the TLB entry for each page */ | ||
| for (ULONG i = 0; i < NumberOfPages; i++) | ||
| { | ||
| __invlpg((PVOID)((ULONG_PTR)Address + (i * PAGE_SIZE))); | ||
| } | ||
| } | ||
|
|
||
| /*! | ||
| * \brief Flushes the current processor's TLB, excluding global pages. | ||
| */ | ||
| FORCEINLINE | ||
| VOID | ||
| KxFlushProcessCurrentTb( | ||
| VOID) | ||
| { | ||
| /* Flush the TLB excluding global pages */ | ||
| __writecr3(__readcr3()); | ||
| } | ||
|
|
||
| /*! | ||
| * \brief Flushes the current processor's entire TLB, including global pages. | ||
| */ | ||
| FORCEINLINE | ||
| VOID | ||
| KxFlushEntireCurrentTb( | ||
| VOID) | ||
| { | ||
| #ifdef _GLOBAL_PAGES_ARE_AWESOME_ | ||
| /* Check if global pages are enabled in CR4 */ | ||
| if (KeFeatureBits & KF_GLOBAL_PAGE) | ||
| { | ||
| /* Disable and restore PGE. This will flush the entire TLB */ | ||
| ULONG64 oldCr4 = __readcr4(); | ||
| __writecr4(oldCr4 & ~CR4_PGE); | ||
| __writecr4(oldCr4); | ||
| } | ||
| else | ||
| #endif | ||
| { | ||
| /* We don't use global pages, reset CR3 instead */ | ||
| __writecr3(__readcr3()); | ||
| } | ||
| } | ||
|
|
||
| #ifdef __cplusplus | ||
| } // extern "C" | ||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -523,14 +523,6 @@ KiGetCacheInformation(VOID) | |
| } | ||
| } | ||
|
|
||
| VOID | ||
| NTAPI | ||
| KeFlushCurrentTb(VOID) | ||
| { | ||
| /* Flush the TLB by resetting CR3 */ | ||
| __writecr3(__readcr3()); | ||
| } | ||
|
|
||
| VOID | ||
| NTAPI | ||
| KiRestoreProcessorControlState(PKPROCESSOR_STATE ProcessorState) | ||
|
|
@@ -649,26 +641,6 @@ KiRestoreProcessorState( | |
| KiRestoreProcessorControlState(&Prcb->ProcessorState); | ||
| } | ||
|
|
||
| VOID | ||
| NTAPI | ||
| KeFlushEntireTb(IN BOOLEAN Invalid, | ||
| IN BOOLEAN AllProcessors) | ||
| { | ||
| KIRQL OldIrql; | ||
|
|
||
| // FIXME: halfplemented | ||
| /* Raise the IRQL for the TB Flush */ | ||
| OldIrql = KeRaiseIrqlToSynchLevel(); | ||
|
|
||
| /* Flush the TB for the Current CPU, and update the flush stamp */ | ||
| KeFlushCurrentTb(); | ||
|
|
||
| /* Update the flush stamp and return to original IRQL */ | ||
| InterlockedExchangeAdd(&KiTbFlushTimeStamp, 1); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, by the way, about this timestamp, you may find this reading interesting: https://azius.com/the-page-fault-in-nonpaged-pool-syndrome/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I am aware of it. We don't make use of this feature and I doubt we ever will, because IMO it's pointless. It doesn't work in user-mode, and in kernel mode there are much better ways to avoid flushes. |
||
| KeLowerIrql(OldIrql); | ||
|
|
||
| } | ||
|
|
||
| NTSTATUS | ||
| NTAPI | ||
| KxSaveFloatingPointState(OUT PKFLOATING_SAVE FloatingState) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -551,6 +551,9 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) | |
| /* Set processor as active */ | ||
| KeActiveProcessors |= 1ULL << Cpu; | ||
|
|
||
| /* We are running the initial system process now */ | ||
| InterlockedOr64(&KiInitialProcess.Pcb.ActiveProcessors, 1ULL << Cpu); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like this is already done in |
||
|
|
||
| /* Release lock */ | ||
| InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -161,11 +161,7 @@ KiSwapContextResume( | |
| NewProcess = NewThread->ApcState.Process; | ||
| if (OldProcess != NewProcess) | ||
| { | ||
| /* Switch address space and flush TLB */ | ||
| __writecr3(NewProcess->DirectoryTableBase[0]); | ||
|
|
||
| /* Set new TSS fields */ | ||
| //Pcr->TssBase->IoMapBase = NewProcess->IopmOffset; | ||
| KiSwapProcess(NewProcess, OldProcess); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: a similar change could be done in x86 in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not an SMP PR and won't change anything in x86 that isn't strictly needed. I'll leave that part to @DarkFire01. |
||
| } | ||
|
|
||
| /* Set TEB pointer and GS base */ | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.