Skip to content

Conversation

tkreuzer
Copy link
Contributor

@tkreuzer tkreuzer commented Apr 26, 2025

Purpose

This PR implements support for global pages (kernel pages that are not flushed out of the TLB on a process switch).

Proposed changes

  • [NDK][NTOS] Implement inline KeGetCurrentProcess
  • [NTOS:KE/x64] Make sure that KPROCESS::ActiveProcessors is set correctly
  • [NTOS:KE] Implement KiIpiSendRequest stub (later used for SMP TLB shootdown)
  • [NTOS::KE] Rewrite TLB flushing (to support SMP and global pages)
  • [NTOS:MM] Implement support for global pages

TODO (not addressed in this PR)

  • Make PDEs global
  • Optimize global VA state lookup with a bitmap

Testbot runs (Filled in by Devs)

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements support for global pages and updates the TLB flushing mechanism across the kernel. Key changes include:

  • Removal of the old inline global page setup in favor of a dedicated MiInitializeGlobalPages() call.
  • Replacement of legacy TLB flush calls (KeFlushCurrentTb, KeFlushProcessTb, etc.) with new Kx-prefixed functions.
  • Introduction of new IPI routines and header updates to support SMP and architectural differences.

Reviewed Changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ntoskrnl/mm/ARM3/i386/init.c Removes inline global page configuration and calls MiInitializeGlobalPages(). Adjusts TLB flush function.
ntoskrnl/mm/ARM3/hypermap.c Updates TLB flushing calls to use KeFlushSingleTb / KeFlushRangeTb.
ntoskrnl/ke/tlbflush.c Adds new implementations for TLB flushing routines supporting SMP.
ntoskrnl/ke/ipi.c and ntoskrnl/ke/amd64/ipi.c Introduces stub and new implementations respectively for IPI requests.
Other files (cpu.c, freeze.c, stubs.c, headers) Update flush functions calls and inline definitions to align with new APIs.
ntoskrnl/include/config.h Enables global page support by defining GLOBAL_PAGES_AWESOME.

@github-actions github-actions bot added the kernel&hal Code changes to the ntoskrnl and HAL label Apr 26, 2025
@HBelusca HBelusca self-requested a review April 26, 2025 15:24
@binarymaster binarymaster added the enhancement For PRs with an enhancement/new feature. label Apr 26, 2025
@github-project-automation github-project-automation bot moved this to New PRs in ReactOS PRs Apr 26, 2025
@binarymaster binarymaster added this to the x64 bringup milestone Apr 26, 2025

VOID
NTAPI
KiIpiSendRequest(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this new version supersedes the old one at line 75, while the function at line 75 appears to be more or less the implementation for KiIpiSend() (of line 36).

KeActiveProcessors |= 1ULL << Cpu;

/* We are running the initial system process now */
InterlockedOr64(&KiInitialProcess.Pcb.ActiveProcessors, 1ULL << Cpu);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like this is already done in KiInitializeHandBuiltThread (see line 134) already, no? (it's invoked either for CPU 0 byKiInitializeKernel() -- which in turn is invoked from KiSystemStartupBootStack, or, it's invoked for CPU != 0 directly by KiSystemStartupBootStack()).


VOID
NTAPI
KeFlushSingleTb(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These main flush Tb functions should raise irql to SYNCH_LEVEL (with KeRaiseIrqlToSynchLevel) and lower it back once finished.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be the point of that?

Copy link
Contributor

@HBelusca HBelusca May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some synchronization issues perhaps (or for using the ipi routines)? I'm just stating what the previous functions were doing, and something that has been observed elsewhere:
https://community.osr.com/t/more-questions-about-mapping-user-kernel-mode-memory/13920/9

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the usual "That's what Windows does" argument. We are not Windows. Our code isn't Windows code. Windows has all kinds of magic sauce, changing from version to version. For example Windows has some timestamp stuff going on (https://azius.com/the-page-fault-in-nonpaged-pool-syndrome/). We don't have that. What we have is either an IPI on SMP, which does the raise already, or simply one or more invlpg instructions. There is nothing to synchronize. In the worst case you'd invalidate TLB entries that have already been invalidated by a cr3 switch.

//
Offset = MI_ZERO_PTES;
PointerPte->u.Hard.PageFrameNumber = Offset;
KeFlushProcessTb();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MiMapPageInHyperSpace at line 69 does a similar flush; why isn't it needed here in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here was that a process flush wouln't work, because these are global PTEs (See line 151). I changed it back to where it was before, just turning it into a global range flush instead of the process flush. It's all not optimal, but it should work just fine. I might improve it in a separate PR.


/* Set new TSS fields */
//Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
KiSwapProcess(NewProcess, OldProcess);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: a similar change could be done in x86 in KiSwapContextExit (compare with the x86 KiSwapProcess implementation) -- this would ensure having the SMP-specific code run there as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

#endif

static const ULONG KxFlushIndividualProcessPagesMaximum = 33; // Based on Linux tlb_single_page_flush_ceiling
static const ULONG KxFlushIndividualGlobalPagesMaximum = 100; // Just a guess
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Use the source, Luke.

{
/* Set it on the template PTE and PDE */
ValidKernelPte.u.Hard.Global = TRUE;
//ValidKernelPde.u.Hard.Global = TRUE; // FIXME: disabled for now
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's happening if you enable this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As usual: crash and burn. PDEs just need more work.

/* Make this a transition PTE */
MI_MAKE_TRANSITION_PTE(PointerPte, Page, Protection);
KeInvalidateTlbEntry(MiAddressToPte(PointerPte));
KeFlushSingleTb(MiAddressToPte(PointerPte), FALSE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noob question (I could have asked it in other places): What dictates the choice of flushing the TLB only for the processors on which the "current" process is running, versus, flushing unconditionally on all processors?

Copy link
Contributor Author

@tkreuzer tkreuzer May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a process local page, then there is no need to flush it on processors that don't run in the context of the current process, because they first need to switch to it, i.e. switch cr3, which flushes the TLB already for non-global pages. And WSLE entries are process local.

KeFlushCurrentTb();

/* Update the flush stamp and return to original IRQL */
InterlockedExchangeAdd(&KiTbFlushTimeStamp, 1);
Copy link
Contributor

Choose a reason for hiding this comment

The 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/
(The MS KB mentioned in the article can be found here.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

@HBelusca HBelusca self-requested a review April 29, 2025 21:28
tkreuzer added 3 commits May 15, 2025 16:21
Assert that only the single zeroing thread calls these functions.
- Add support for global pages
- Add support for SMP
- Improve naming to be more explicit about what the individual functions do
- Unify shared code
@tkreuzer tkreuzer force-pushed the ntos/global_pages branch from 8d8c2ff to 12d75df Compare June 12, 2025 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement For PRs with an enhancement/new feature. kernel&hal Code changes to the ntoskrnl and HAL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants