[NTOS:EX/KE][HALX86] Add support for NUMPROC, BOOTPROC, MAXPROC, ONECPU boot switches (#6024)

These SMP-specific switches allow to test and control configurations
with various number of CPUs on multiprocessor systems.

- NUMPROC: maximum number of logical processors that can be started
  (including dynamically, not currently supported by ReactOS) at run-time.

- BOOTPROC: maximum number of logical processors that can be started at
  boot-time.

- MAXPROC: forces the OS to report the maximum possible number of CPUs
  as existing on the system.

- ONECPU (MP HAL-only boot switch): causes the HAL to only use one
  (the boot) CPU on a multiprocessor system. Attempting to start other
  processors will fail.

For more information, see:
https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/numproc.htm
https://www.geoffchappell.com/notes/windows/license/processors.htm
https://rmscrypt.wordpress.com/2011/02/
https://codeinsecurity.wordpress.com/2022/04/07/cpu-socket-and-core-count-limits-in-windows-10-and-how-to-remove-them/

Generic references about BOOT.INI switches:
https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/boot-options-in-a-boot-ini-file
https://www.itprotoday.com/cloud-computing/what-switches-can-be-used-bootini
http://franck.kiechel.free.fr/dbr_eng/BootIni.htm

References about BCD options:
https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--set
http://www.mistyprojects.co.uk/documents/BCDEdit/files/commands.6.1.7601.htm#TYPES%20OSLOADER
This commit is contained in:
Hermès Bélusca-Maïto 2023-11-20 21:35:57 +01:00
parent 7093412f4e
commit 3022d74beb
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
6 changed files with 90 additions and 6 deletions

View file

@ -14,6 +14,9 @@
/* GLOBALS *******************************************************************/
//#ifdef CONFIG_SMP // FIXME: Reenable conditional once HAL is consistently compiled for SMP mode
BOOLEAN HalpOnlyBootProcessor;
//#endif
BOOLEAN HalpPciLockSettings;
/* PRIVATE FUNCTIONS *********************************************************/
@ -30,6 +33,12 @@ HalpGetParameters(
/* Read the command line */
PCSTR CommandLine = LoaderBlock->LoadOptions;
//#ifdef CONFIG_SMP // FIXME: Reenable conditional once HAL is consistently compiled for SMP mode
/* Check whether we should only start one CPU */
if (strstr(CommandLine, "ONECPU"))
HalpOnlyBootProcessor = TRUE;
//#endif
/* Check if PCI is locked */
if (strstr(CommandLine, "PCILOCK"))
HalpPciLockSettings = TRUE;

View file

@ -16,6 +16,8 @@
/* GLOBALS *******************************************************************/
extern BOOLEAN HalpOnlyBootProcessor;
extern PPROCESSOR_IDENTITY HalpProcessorIdentity;
extern PHYSICAL_ADDRESS HalpLowStubPhysicalAddress;
extern PVOID HalpLowStub;
@ -88,6 +90,11 @@ HalStartNextProcessor(
_In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
_In_ PKPROCESSOR_STATE ProcessorState)
{
/* Bail out if we only use the boot CPU */
if (HalpOnlyBootProcessor)
return FALSE;
/* Bail out if we have started all available CPUs */
if (HalpStartedProcessorCount == HalpApicInfoTable.ProcessorCount)
return FALSE;

View file

@ -1559,6 +1559,34 @@ Phase1InitializationDiscard(IN PVOID Context)
}
#ifdef CONFIG_SMP
/*
* IMPORTANT NOTE:
* Because ReactOS is a "nice" OS, we do not care _at all_
* about any number of registered/licensed processors:
* no usage of KeRegisteredProcessors nor KeLicensedProcessors.
*/
if (CommandLine)
{
PSTR Option;
/* Check for NUMPROC: maximum number of logical processors
* that can be started (including dynamically) at run-time */
Option = strstr(CommandLine, "NUMPROC");
if (Option) Option = strstr(Option, "=");
if (Option) KeNumprocSpecified = atol(Option + 1);
/* Check for BOOTPROC (NT6+ and ReactOS): maximum number
* of logical processors that can be started at boot-time */
Option = strstr(CommandLine, "BOOTPROC");
if (Option) Option = strstr(Option, "=");
if (Option) KeBootprocSpecified = atol(Option + 1);
/* Check for MAXPROC (NT6+ and ReactOS): forces the kernel to report
* as existing the maximum number of processors that can be handled */
if (strstr(CommandLine, "MAXPROC"))
KeMaximumProcessors = MAXIMUM_PROCESSORS;
}
/* Start Application Processors */
KeStartAllProcessors();
#endif

View file

@ -90,7 +90,6 @@ typedef PCHAR
IN ULONG Length
);
extern KAFFINITY KeActiveProcessors;
extern PKNMI_HANDLER_CALLBACK KiNmiCallbackListHead;
extern KSPIN_LOCK KiNmiCallbackListLock;
extern PVOID KeUserApcDispatcher;
@ -104,6 +103,13 @@ extern USHORT KeProcessorArchitecture;
extern USHORT KeProcessorLevel;
extern USHORT KeProcessorRevision;
extern ULONG64 KeFeatureBits;
extern KAFFINITY KeActiveProcessors;
extern PKPRCB KiProcessorBlock[];
#ifdef CONFIG_SMP
extern ULONG KeMaximumProcessors;
extern ULONG KeNumprocSpecified;
extern ULONG KeBootprocSpecified;
#endif
extern KNODE KiNode0;
extern PKNODE KeNodeBlock[1];
extern UCHAR KeNumberNodes;
@ -136,7 +142,6 @@ extern LIST_ENTRY KiProcessListHead;
extern LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
extern LIST_ENTRY KiStackInSwapListHead;
extern KEVENT KiSwapEvent;
extern PKPRCB KiProcessorBlock[];
extern KAFFINITY KiIdleSummary;
extern PVOID KeUserApcDispatcher;
extern PVOID KeUserCallbackDispatcher;

View file

@ -9,6 +9,7 @@
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
@ -38,12 +39,28 @@ NTAPI
KeStartAllProcessors(VOID)
{
PVOID KernelStack, DPCStack;
ULONG ProcessorCount = 0;
PAPINFO APInfo;
ULONG ProcessorCount;
ULONG MaximumProcessors;
while (TRUE)
/* NOTE: NT6+ HAL exports HalEnumerateProcessors() and
* HalQueryMaximumProcessorCount() that help determining
* the number of detected processors on the system. */
MaximumProcessors = KeMaximumProcessors;
/* Limit the number of processors we can start at run-time */
if (KeNumprocSpecified)
MaximumProcessors = min(MaximumProcessors, KeNumprocSpecified);
/* Limit also the number of processors we can start during boot-time */
if (KeBootprocSpecified)
MaximumProcessors = min(MaximumProcessors, KeBootprocSpecified);
// TODO: Support processor nodes
/* Start ProcessorCount at 1 because we already have the boot CPU */
for (ProcessorCount = 1; ProcessorCount < MaximumProcessors; ++ProcessorCount)
{
ProcessorCount++;
KernelStack = NULL;
DPCStack = NULL;

View file

@ -13,9 +13,27 @@
/* GLOBALS *******************************************************************/
CCHAR KeNumberProcessors = 0;
KAFFINITY KeActiveProcessors = 0;
/* Number of processors */
CCHAR KeNumberProcessors = 0;
#ifdef CONFIG_SMP
/* Theoretical maximum number of processors that can be handled.
* Set once at run-time. Returned by KeQueryMaximumProcessorCount(). */
ULONG KeMaximumProcessors = MAXIMUM_PROCESSORS;
/* Maximum number of logical processors that can be started
* (including dynamically) at run-time. If 0: do not perform checks. */
ULONG KeNumprocSpecified = 0;
/* Maximum number of logical processors that can be started
* at boot-time. If 0: do not perform checks. */
ULONG KeBootprocSpecified = 0;
#endif // CONFIG_SMP
/* FUNCTIONS *****************************************************************/
KAFFINITY