From 43c47fa625c1bfa27c911c7eb7a193c022148ba1 Mon Sep 17 00:00:00 2001 From: Arnaud Bouchez Date: Tue, 8 Feb 2022 10:41:39 +0100 Subject: [PATCH] enhanced CPU/cache information retrieval - if no CPU is detected, a generic name is used, with known HW abilities on ARM (has been observed with a VM on Apple M1) - retrieve the cache info on Darwin/MacOS --- src/core/mormot.core.os.pas | 11 +++--- src/core/mormot.core.os.posix.inc | 64 +++++++++++++++++++++++-------- src/crypt/mormot.crypt.core.pas | 12 ++++++ 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/core/mormot.core.os.pas b/src/core/mormot.core.os.pas index 6983fb1f3..e87d07b40 100644 --- a/src/core/mormot.core.os.pas +++ b/src/core/mormot.core.os.pas @@ -591,15 +591,14 @@ EOSException = class(Exception); // - contains e.g. 'LENOVO 20HES23B0U ThinkPad T470' BiosInfoText: RawUtf8; - {$ifdef OSWINDOWS} /// Level 1 to 4 CPU caches as returned by GetLogicalProcessorInformation // - yes, Intel introduced a Level 4 cache (eDRAM) with some Haswell/Iris CPUs - // - we don't retrieve this information from Linux / POSIX yet + // - this information is not retrieved on all Linux / POSIX systems yet // - only Unified or Data caches are include (not Instruction or Trace) + // - note: some CPU - like the Apple M1 - have 128 bytes of LineSize CpuCache: array[1..4] of record Count, Size, LineSize: cardinal; end; - {$endif OSWINDOWS} {$ifdef OSLINUXANDROID} /// contains the Flags: or Features: value of Linux /proc/cpuinfo @@ -4190,13 +4189,13 @@ procedure RaiseLastModuleError(ModuleName: PChar; ModuleException: ExceptClass); function Unicode_CodePage: integer; begin -{$ifdef FPC} + {$ifdef FPC} // = GetSystemCodePage on POSIX, Lazarus may override to UTF-8 on Windows result := DefaultSystemCodePage; -{$else} + {$else} // Delphi always uses the main Windows System Code Page result := GetACP; -{$endif FPC} + {$endif FPC} end; function Unicode_CompareString(PW1, PW2: PWideChar; L1, L2: PtrInt; diff --git a/src/core/mormot.core.os.posix.inc b/src/core/mormot.core.os.posix.inc index 1644cfacc..478e283aa 100644 --- a/src/core/mormot.core.os.posix.inc +++ b/src/core/mormot.core.os.posix.inc @@ -2262,6 +2262,8 @@ function getpagesize: integer; cdecl; external clib; {$ifdef OSLINUX} +function get_nprocs: integer; cdecl; external clib; + procedure SetLinuxDistrib(const release: RawUtf8); var distrib: TOperatingSystem; @@ -2440,6 +2442,25 @@ procedure crc32blocksarm64(crc128, data128: PBlock128; count: integer); external {$endif CPUAARCH64} +function KB(Size: cardinal): shortstring; +begin + if Size >= 1 shl 30 then + begin + str(Size shr 30, result); + result := result + 'GB'; + end + else if Size >= 1 shl 20 then + begin + str(Size shr 20, result); + result := result + 'MB'; + end + else + begin + str(Size shr 10, result); + result := result + 'KB'; + end +end; + procedure InitializeSpecificUnit; var P: PAnsiChar; @@ -2482,6 +2503,17 @@ begin modname := fpsysctlhwstr(HW_MODEL, temp); with uts do OSVersionText := sysname + '-' + release + ' ' + version; + {$ifdef OSDARWIN} + CpuCache[1].LineSize := fpsysctlhwint(HW_CACHELINE); + CpuCache[1].Size := fpsysctlhwint(HW_L1DCACHESIZE); + CpuCache[2].LineSize := fpsysctlhwint(HW_CACHELINE); + CpuCache[2].Size := fpsysctlhwint(HW_L2CACHESIZE); + CpuCacheSize := CpuCache[2].Size; + if CpuCacheSize = 0 then + CpuCacheSize := CpuCache[1].Size; + if CpuCacheSize <> 0 then + CpuCacheText := 'L1=' + KB(CpuCache[1].Size) + ' L2=' + KB(CpuCache[2].Size); + {$endif OSDARWIN} {$else} {$ifdef OSANDROID} release := GetSystemProperty('ro.build.version.release'); @@ -2606,30 +2638,19 @@ begin CpuCacheSize := GetNextCardinal(cache); while cache^ = ' ' do inc(cache); - case cache^ of - 'k', + case upcase(cache^) of 'K': CpuCacheSize := CpuCacheSize shl 10; - 'm', 'M': CpuCacheSize := CpuCacheSize shl 20; - 'g', 'G': CpuCacheSize := CpuCacheSize shl 30; end; - if CpuCacheSize < 1 shl 20 then - begin - str(CpuCacheSize shr 10, CpuInfoText); - CpuInfoText := CpuInfoText + 'KB cache'; - end - else - begin - str(CpuCacheSize shr 20, CpuInfoText); - CpuInfoText := CpuInfoText + 'MB cache'; - end; end; SystemInfo.release := release; {$endif OSBSDDARWIN} + if CpuCacheSize <> 0 then + CpuInfoText := KB(CpuCacheSize) + ' cache'; SystemInfo.uts.release := uts.Release; SystemInfo.uts.sysname := uts.Sysname; SystemInfo.uts.version := uts.Version; @@ -2638,16 +2659,25 @@ begin GetNextCardinal(P) shl 8 + GetNextCardinal(P); OSVersion32.os := OS_KIND; - MoveSmall(@KernelRevision, @OSVersion32.utsrelease, SizeOf(OSVersion32.utsrelease)); + MoveSmall(@KernelRevision, @OSVersion32.utsrelease, 3); // 24-bit version with SystemInfo.uts do OSVersionText := sysname + ' ' + release; if SystemInfo.release <> '' then OSVersionText := SystemInfo.release + ' - ' + OSVersionText; {$ifdef OSANDROID} OSVersionText := 'Android (' + OSVersionText + ')'; + {$else} + {$ifdef OSLINUX} + if SystemInfo.dwNumberOfProcessors = 0 then // e.g. QEMU limited /proc/cpuinfo + SystemInfo.dwNumberOfProcessors := get_nprocs; + {$endif OSLINUX} {$endif OSANDROID} - if (SystemInfo.dwNumberOfProcessors > 0) and - (modname <> nil) then + if SystemInfo.dwNumberOfProcessors = 0 then + SystemInfo.dwNumberOfProcessors := 1; + if modname = nil then + CpuInfoText := Format('%d x generic ' + CPU_ARCH_TEXT + ' cpu %s', + [SystemInfo.dwNumberOfProcessors, CpuInfoText]) + else CpuInfoText := Format('%d x %s %s (' + CPU_ARCH_TEXT + ')', [SystemInfo.dwNumberOfProcessors, modname, CpuInfoText]); if CpuInfoText = '' then diff --git a/src/crypt/mormot.crypt.core.pas b/src/crypt/mormot.crypt.core.pas index afe7e5c79..4d3d0c833 100644 --- a/src/crypt/mormot.crypt.core.pas +++ b/src/crypt/mormot.crypt.core.pas @@ -10420,6 +10420,7 @@ procedure InitializeUnit; rk: TKeyArray; bi, bo: TAesBlock; shablock: array[0..63] of byte; + i: PtrInt; {$endif USEARMCRYPTO} begin ComputeAesStaticTables; @@ -10492,6 +10493,17 @@ procedure InitializeUnit; // ARMv8 SHA HW opcodes seem not available exclude(CpuFeatures, ahcSha2); end; + i := PosEx('x generic', CpuInfoText); + if i <> 0 then + begin // some VM/QEMU software don't actually return a proper CPU name + inc(i, 9); + if ahcCRC32 in CpuFeatures then + insert(' crc', CpuInfoText, i); + if ahcSha2 in CpuFeatures then + insert(' sha', CpuInfoText, i); + if ahcAes in CpuFeatures then + insert(' aes', CpuInfoText, i); + end; {$endif USEARMCRYPTO} assert(SizeOf(TMd5Buf) = SizeOf(TMd5Digest)); assert(SizeOf(TAes) = AES_CONTEXT_SIZE);