From 3867a9d8f06c4699cd25cfbd5bb7a8f7855cdcd2 Mon Sep 17 00:00:00 2001 From: Weiteng Chen Date: Tue, 4 Aug 2026 13:11:29 -0700 Subject: [PATCH 1/2] Report NUMA and processor topology Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- litebox_shim_windows/src/lib.rs | 3 + litebox_shim_windows/src/syscalls/mod.rs | 8 ++ litebox_shim_windows/src/syscalls/sysinfo.rs | 91 ++++++++++++++++++-- 3 files changed, 96 insertions(+), 6 deletions(-) diff --git a/litebox_shim_windows/src/lib.rs b/litebox_shim_windows/src/lib.rs index 8c7259849..9ac4f463d 100644 --- a/litebox_shim_windows/src/lib.rs +++ b/litebox_shim_windows/src/lib.rs @@ -1396,6 +1396,9 @@ impl Task { byte_offset, key, ), + SyscallRequest::NtGetCurrentProcessorNumberEx { processor_number } => { + self.sys_nt_get_current_processor_number_ex(processor_number) + } SyscallRequest::NtQueryDebugFilterState { component_id, level, diff --git a/litebox_shim_windows/src/syscalls/mod.rs b/litebox_shim_windows/src/syscalls/mod.rs index 3cd16c160..044df363f 100644 --- a/litebox_shim_windows/src/syscalls/mod.rs +++ b/litebox_shim_windows/src/syscalls/mod.rs @@ -374,6 +374,9 @@ pub(crate) enum SyscallRequest { byte_offset: Option>, key: Option>, }, + NtGetCurrentProcessorNumberEx { + processor_number: Platform::RawMutPointer, + }, NtQueryDebugFilterState { component_id: u32, level: u32, @@ -1059,6 +1062,11 @@ impl SyscallRequest { byte_offset:*, key:*, })), + NtSysno::NtGetCurrentProcessorNumberEx => { + Some(sys_req!(NtGetCurrentProcessorNumberEx { + processor_number:*, + })) + } NtSysno::NtQueryDebugFilterState => Some(sys_req!(NtQueryDebugFilterState { component_id, level, diff --git a/litebox_shim_windows/src/syscalls/sysinfo.rs b/litebox_shim_windows/src/syscalls/sysinfo.rs index 81bee02c6..a25e1b003 100644 --- a/litebox_shim_windows/src/syscalls/sysinfo.rs +++ b/litebox_shim_windows/src/syscalls/sysinfo.rs @@ -36,6 +36,14 @@ const SYSTEM_VERIFIER_INFORMATION_LENGTH: u32 = 0x90; const SYSTEM_VERIFIER_INFORMATION_LENGTH_USIZE: usize = 0x90; const X64_SYSTEM_RANGE_START: usize = 0xffff_8000_0000_0000; +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, FromBytes, Immutable, IntoBytes)] +pub(crate) struct ProcessorNumber { + group: u16, + number: u8, + reserved: u8, +} + pub(crate) const WINDOWS_TIME_ZONE_ID_INVALID: u32 = u32::MAX; pub(crate) const WINDOWS_OS_MAJOR_VERSION: u16 = 10; pub(crate) const WINDOWS_OS_MINOR_VERSION: u16 = 0; @@ -71,6 +79,7 @@ enum LogicalProcessorRelationship { Cache = 2, ProcessorPackage = 3, Group = 4, + NumaNodeEx = 6, All = 0xffff, } @@ -219,6 +228,23 @@ struct GroupRelationshipInformation { } impl Task { + #[expect( + clippy::unused_self, + reason = "syscall handlers consistently operate on the current task" + )] + pub(crate) fn sys_nt_get_current_processor_number_ex( + &self, + processor_number: MutPtr, + ) -> NtStatus { + if processor_number + .write_at_offset(0, ProcessorNumber::default()) + .is_none() + { + return NtStatus::ACCESS_VIOLATION; + } + NtStatus::SUCCESS + } + pub(crate) fn sys_nt_query_system_information( system_information_class: u32, system_information: MutPtr, @@ -384,12 +410,17 @@ impl Task { return_length, &processor_relationship_information(LogicalProcessorRelationship::ProcessorCore), ), - LogicalProcessorRelationship::NumaNode => Self::write_system_information( - system_information, - system_information_length, - return_length, - &numa_node_relationship_information(), - ), + // Windows returns RelationNumaNode-tagged records for a RelationNumaNodeEx query. + // The synthetic topology has one processor group, so the existing one-element + // GroupMasks array is the complete extended-NUMA response. + LogicalProcessorRelationship::NumaNode | LogicalProcessorRelationship::NumaNodeEx => { + Self::write_system_information( + system_information, + system_information_length, + return_length, + &numa_node_relationship_information(), + ) + } LogicalProcessorRelationship::Cache => Self::write_system_information( system_information, system_information_length, @@ -850,6 +881,25 @@ mod tests { ConstPtr::::from_usize(core::ptr::from_ref(value).cast::() as usize) } + #[test] + fn nt_get_current_processor_number_ex_reports_synthetic_processor() { + run_with_test_platform_pointers(|| { + let mut processor_number = ProcessorNumber { + group: u16::MAX, + number: u8::MAX, + reserved: u8::MAX, + }; + assert_eq!( + crate::tests::test_task() + .sys_nt_get_current_processor_number_ex(mut_ptr(&mut processor_number)), + NtStatus::SUCCESS + ); + assert_eq!(processor_number.group, 0); + assert_eq!(processor_number.number, 0); + assert_eq!(processor_number.reserved, 0); + }); + } + #[test] fn nt_query_system_information_ex_validates_query_input() { run_with_test_platform_pointers(|| { @@ -976,6 +1026,35 @@ mod tests { }); } + #[test] + fn nt_query_system_information_ex_reports_extended_numa_node() { + run_with_test_platform_pointers(|| { + let relationship = LogicalProcessorRelationship::NumaNodeEx as u32; + let mut output = [0u8; size_of::()]; + let mut return_length = 0; + assert_eq!( + TestTask::sys_nt_query_system_information_ex( + SystemInformationClass::LogicalProcessorAndGroup as u32, + Some(const_byte_ptr(&relationship)), + DWORD_SIZE_U32, + mut_byte_ptr(&mut output), + output.len().try_into().unwrap(), + Some(mut_ptr(&mut return_length)), + ), + NtStatus::SUCCESS + ); + assert_eq!( + return_length, + size_of::().trunc() + ); + assert_eq!( + u32::from_ne_bytes(output[..4].try_into().unwrap()), + LogicalProcessorRelationship::NumaNode as u32 + ); + assert_eq!(u16::from_ne_bytes(output[30..32].try_into().unwrap()), 1); + }); + } + #[test] fn nt_query_system_information_reports_basic_information() { run_with_test_platform_pointers(|| { From 6b2b09de14d388fefcde54f28d765c7f274f8eda Mon Sep 17 00:00:00 2001 From: Weiteng Chen Date: Wed, 5 Aug 2026 17:06:43 -0700 Subject: [PATCH 2/2] remove test --- litebox_shim_windows/src/syscalls/sysinfo.rs | 57 +++----------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/litebox_shim_windows/src/syscalls/sysinfo.rs b/litebox_shim_windows/src/syscalls/sysinfo.rs index a25e1b003..1ca1a7ca9 100644 --- a/litebox_shim_windows/src/syscalls/sysinfo.rs +++ b/litebox_shim_windows/src/syscalls/sysinfo.rs @@ -237,7 +237,14 @@ impl Task { processor_number: MutPtr, ) -> NtStatus { if processor_number - .write_at_offset(0, ProcessorNumber::default()) + .write_at_offset( + 0, + ProcessorNumber { + group: 0, + number: 0, + reserved: 0, + }, + ) .is_none() { return NtStatus::ACCESS_VIOLATION; @@ -881,25 +888,6 @@ mod tests { ConstPtr::::from_usize(core::ptr::from_ref(value).cast::() as usize) } - #[test] - fn nt_get_current_processor_number_ex_reports_synthetic_processor() { - run_with_test_platform_pointers(|| { - let mut processor_number = ProcessorNumber { - group: u16::MAX, - number: u8::MAX, - reserved: u8::MAX, - }; - assert_eq!( - crate::tests::test_task() - .sys_nt_get_current_processor_number_ex(mut_ptr(&mut processor_number)), - NtStatus::SUCCESS - ); - assert_eq!(processor_number.group, 0); - assert_eq!(processor_number.number, 0); - assert_eq!(processor_number.reserved, 0); - }); - } - #[test] fn nt_query_system_information_ex_validates_query_input() { run_with_test_platform_pointers(|| { @@ -1026,35 +1014,6 @@ mod tests { }); } - #[test] - fn nt_query_system_information_ex_reports_extended_numa_node() { - run_with_test_platform_pointers(|| { - let relationship = LogicalProcessorRelationship::NumaNodeEx as u32; - let mut output = [0u8; size_of::()]; - let mut return_length = 0; - assert_eq!( - TestTask::sys_nt_query_system_information_ex( - SystemInformationClass::LogicalProcessorAndGroup as u32, - Some(const_byte_ptr(&relationship)), - DWORD_SIZE_U32, - mut_byte_ptr(&mut output), - output.len().try_into().unwrap(), - Some(mut_ptr(&mut return_length)), - ), - NtStatus::SUCCESS - ); - assert_eq!( - return_length, - size_of::().trunc() - ); - assert_eq!( - u32::from_ne_bytes(output[..4].try_into().unwrap()), - LogicalProcessorRelationship::NumaNode as u32 - ); - assert_eq!(u16::from_ne_bytes(output[30..32].try_into().unwrap()), 1); - }); - } - #[test] fn nt_query_system_information_reports_basic_information() { run_with_test_platform_pointers(|| {