1*6777b538SAndroid Build Coastguard Worker// Copyright 2016 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker#include "base/system/sys_info.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker#import <Foundation/Foundation.h> 8*6777b538SAndroid Build Coastguard Worker#include <mach/mach_host.h> 9*6777b538SAndroid Build Coastguard Worker#include <mach/mach_init.h> 10*6777b538SAndroid Build Coastguard Worker#include <stddef.h> 11*6777b538SAndroid Build Coastguard Worker#include <stdint.h> 12*6777b538SAndroid Build Coastguard Worker#include <sys/sysctl.h> 13*6777b538SAndroid Build Coastguard Worker#include <sys/types.h> 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker#include <optional> 16*6777b538SAndroid Build Coastguard Worker#include <string_view> 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker#include "base/apple/scoped_mach_port.h" 19*6777b538SAndroid Build Coastguard Worker#include "base/check_op.h" 20*6777b538SAndroid Build Coastguard Worker#include "base/debug/stack_trace.h" 21*6777b538SAndroid Build Coastguard Worker#include "base/feature_list.h" 22*6777b538SAndroid Build Coastguard Worker#include "base/mac/mac_util.h" 23*6777b538SAndroid Build Coastguard Worker#include "base/no_destructor.h" 24*6777b538SAndroid Build Coastguard Worker#include "base/notreached.h" 25*6777b538SAndroid Build Coastguard Worker#include "base/numerics/safe_conversions.h" 26*6777b538SAndroid Build Coastguard Worker#include "base/posix/sysctl.h" 27*6777b538SAndroid Build Coastguard Worker#include "base/process/process_metrics.h" 28*6777b538SAndroid Build Coastguard Worker#include "base/strings/string_number_conversions.h" 29*6777b538SAndroid Build Coastguard Worker#include "base/strings/string_util.h" 30*6777b538SAndroid Build Coastguard Worker#include "base/strings/stringprintf.h" 31*6777b538SAndroid Build Coastguard Worker#include "base/synchronization/lock.h" 32*6777b538SAndroid Build Coastguard Worker#include "base/system/sys_info_internal.h" 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Workernamespace base { 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard Workernamespace { 37*6777b538SAndroid Build Coastguard Worker 38*6777b538SAndroid Build Coastguard Worker// Whether this process has CPU security mitigations enabled. 39*6777b538SAndroid Build Coastguard Workerbool g_is_cpu_security_mitigation_enabled = false; 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker// Whether NumberOfProcessors() was called. Used to detect when the CPU security 42*6777b538SAndroid Build Coastguard Worker// mitigations state changes after a call to NumberOfProcessors(). 43*6777b538SAndroid Build Coastguard Workerbool g_is_cpu_security_mitigation_enabled_read = false; 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker} // namespace 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Workernamespace internal { 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Workerstd::optional<int> NumberOfPhysicalProcessors() { 50*6777b538SAndroid Build Coastguard Worker return GetSysctlIntValue("hw.physicalcpu_max"); 51*6777b538SAndroid Build Coastguard Worker} 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Workerstd::optional<int> NumberOfProcessorsWhenCpuSecurityMitigationEnabled() { 54*6777b538SAndroid Build Coastguard Worker g_is_cpu_security_mitigation_enabled_read = true; 55*6777b538SAndroid Build Coastguard Worker 56*6777b538SAndroid Build Coastguard Worker if (!g_is_cpu_security_mitigation_enabled || 57*6777b538SAndroid Build Coastguard Worker !FeatureList::IsEnabled(kNumberOfCoresWithCpuSecurityMitigation)) { 58*6777b538SAndroid Build Coastguard Worker return std::nullopt; 59*6777b538SAndroid Build Coastguard Worker } 60*6777b538SAndroid Build Coastguard Worker return NumberOfPhysicalProcessors(); 61*6777b538SAndroid Build Coastguard Worker} 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard Worker} // namespace internal 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard WorkerBASE_FEATURE(kNumberOfCoresWithCpuSecurityMitigation, 66*6777b538SAndroid Build Coastguard Worker "NumberOfCoresWithCpuSecurityMitigation", 67*6777b538SAndroid Build Coastguard Worker FEATURE_ENABLED_BY_DEFAULT); 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker// static 70*6777b538SAndroid Build Coastguard Workerstd::string SysInfo::OperatingSystemName() { 71*6777b538SAndroid Build Coastguard Worker return "Mac OS X"; 72*6777b538SAndroid Build Coastguard Worker} 73*6777b538SAndroid Build Coastguard Worker 74*6777b538SAndroid Build Coastguard Worker// static 75*6777b538SAndroid Build Coastguard Workerstd::string SysInfo::OperatingSystemVersion() { 76*6777b538SAndroid Build Coastguard Worker int32_t major, minor, bugfix; 77*6777b538SAndroid Build Coastguard Worker OperatingSystemVersionNumbers(&major, &minor, &bugfix); 78*6777b538SAndroid Build Coastguard Worker return base::StringPrintf("%d.%d.%d", major, minor, bugfix); 79*6777b538SAndroid Build Coastguard Worker} 80*6777b538SAndroid Build Coastguard Worker 81*6777b538SAndroid Build Coastguard Worker// static 82*6777b538SAndroid Build Coastguard Workervoid SysInfo::OperatingSystemVersionNumbers(int32_t* major_version, 83*6777b538SAndroid Build Coastguard Worker int32_t* minor_version, 84*6777b538SAndroid Build Coastguard Worker int32_t* bugfix_version) { 85*6777b538SAndroid Build Coastguard Worker NSOperatingSystemVersion version = 86*6777b538SAndroid Build Coastguard Worker NSProcessInfo.processInfo.operatingSystemVersion; 87*6777b538SAndroid Build Coastguard Worker *major_version = saturated_cast<int32_t>(version.majorVersion); 88*6777b538SAndroid Build Coastguard Worker *minor_version = saturated_cast<int32_t>(version.minorVersion); 89*6777b538SAndroid Build Coastguard Worker *bugfix_version = saturated_cast<int32_t>(version.patchVersion); 90*6777b538SAndroid Build Coastguard Worker} 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard Worker// static 93*6777b538SAndroid Build Coastguard Workerstd::string SysInfo::OperatingSystemArchitecture() { 94*6777b538SAndroid Build Coastguard Worker switch (mac::GetCPUType()) { 95*6777b538SAndroid Build Coastguard Worker case mac::CPUType::kIntel: 96*6777b538SAndroid Build Coastguard Worker return "x86_64"; 97*6777b538SAndroid Build Coastguard Worker case mac::CPUType::kTranslatedIntel: 98*6777b538SAndroid Build Coastguard Worker case mac::CPUType::kArm: 99*6777b538SAndroid Build Coastguard Worker return "arm64"; 100*6777b538SAndroid Build Coastguard Worker } 101*6777b538SAndroid Build Coastguard Worker} 102*6777b538SAndroid Build Coastguard Worker 103*6777b538SAndroid Build Coastguard Worker// static 104*6777b538SAndroid Build Coastguard Workeruint64_t SysInfo::AmountOfPhysicalMemoryImpl() { 105*6777b538SAndroid Build Coastguard Worker struct host_basic_info hostinfo; 106*6777b538SAndroid Build Coastguard Worker mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; 107*6777b538SAndroid Build Coastguard Worker base::apple::ScopedMachSendRight host(mach_host_self()); 108*6777b538SAndroid Build Coastguard Worker int result = host_info(host.get(), HOST_BASIC_INFO, 109*6777b538SAndroid Build Coastguard Worker reinterpret_cast<host_info_t>(&hostinfo), &count); 110*6777b538SAndroid Build Coastguard Worker if (result != KERN_SUCCESS) { 111*6777b538SAndroid Build Coastguard Worker NOTREACHED(); 112*6777b538SAndroid Build Coastguard Worker return 0; 113*6777b538SAndroid Build Coastguard Worker } 114*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(HOST_BASIC_INFO_COUNT, count); 115*6777b538SAndroid Build Coastguard Worker return hostinfo.max_mem; 116*6777b538SAndroid Build Coastguard Worker} 117*6777b538SAndroid Build Coastguard Worker 118*6777b538SAndroid Build Coastguard Worker// static 119*6777b538SAndroid Build Coastguard Workeruint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() { 120*6777b538SAndroid Build Coastguard Worker SystemMemoryInfoKB info; 121*6777b538SAndroid Build Coastguard Worker if (!GetSystemMemoryInfo(&info)) 122*6777b538SAndroid Build Coastguard Worker return 0; 123*6777b538SAndroid Build Coastguard Worker // We should add inactive file-backed memory also but there is no such 124*6777b538SAndroid Build Coastguard Worker // information from Mac OS unfortunately. 125*6777b538SAndroid Build Coastguard Worker return checked_cast<uint64_t>(info.free + info.speculative) * 1024; 126*6777b538SAndroid Build Coastguard Worker} 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker// static 129*6777b538SAndroid Build Coastguard Workerstd::string SysInfo::CPUModelName() { 130*6777b538SAndroid Build Coastguard Worker return StringSysctlByName("machdep.cpu.brand_string").value_or(std::string{}); 131*6777b538SAndroid Build Coastguard Worker} 132*6777b538SAndroid Build Coastguard Worker 133*6777b538SAndroid Build Coastguard Worker// static 134*6777b538SAndroid Build Coastguard Workerstd::string SysInfo::HardwareModelName() { 135*6777b538SAndroid Build Coastguard Worker // The old "hw.machine" and "hw.model" sysctls are discouraged in favor of the 136*6777b538SAndroid Build Coastguard Worker // new "hw.product" and "hw.target". See 137*6777b538SAndroid Build Coastguard Worker // https://github.com/apple-oss-distributions/xnu/blob/aca3beaa3dfbd42498b42c5e5ce20a938e6554e5/bsd/sys/sysctl.h#L1168-L1169 138*6777b538SAndroid Build Coastguard Worker // and 139*6777b538SAndroid Build Coastguard Worker // https://github.com/apple-oss-distributions/xnu/blob/aca3beaa3dfbd42498b42c5e5ce20a938e6554e5/bsd/kern/kern_mib.c#L534-L536 140*6777b538SAndroid Build Coastguard Worker if (base::mac::MacOSMajorVersion() < 11) { 141*6777b538SAndroid Build Coastguard Worker return StringSysctl({CTL_HW, HW_MODEL}).value_or(std::string{}); 142*6777b538SAndroid Build Coastguard Worker } else { 143*6777b538SAndroid Build Coastguard Worker return StringSysctl({CTL_HW, HW_PRODUCT}).value_or(std::string{}); 144*6777b538SAndroid Build Coastguard Worker } 145*6777b538SAndroid Build Coastguard Worker} 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker// static 148*6777b538SAndroid Build Coastguard Workerstd::optional<SysInfo::HardwareModelNameSplit> 149*6777b538SAndroid Build Coastguard WorkerSysInfo::SplitHardwareModelNameDoNotUse(std::string_view name) { 150*6777b538SAndroid Build Coastguard Worker size_t number_loc = name.find_first_of("0123456789"); 151*6777b538SAndroid Build Coastguard Worker if (number_loc == std::string::npos) { 152*6777b538SAndroid Build Coastguard Worker return std::nullopt; 153*6777b538SAndroid Build Coastguard Worker } 154*6777b538SAndroid Build Coastguard Worker size_t comma_loc = name.find(',', number_loc); 155*6777b538SAndroid Build Coastguard Worker if (comma_loc == std::string::npos) { 156*6777b538SAndroid Build Coastguard Worker return std::nullopt; 157*6777b538SAndroid Build Coastguard Worker } 158*6777b538SAndroid Build Coastguard Worker 159*6777b538SAndroid Build Coastguard Worker HardwareModelNameSplit split; 160*6777b538SAndroid Build Coastguard Worker if (!StringToInt(name.substr(0u, comma_loc).substr(number_loc), 161*6777b538SAndroid Build Coastguard Worker &split.model) || 162*6777b538SAndroid Build Coastguard Worker !StringToInt(name.substr(comma_loc + 1), &split.variant)) { 163*6777b538SAndroid Build Coastguard Worker return std::nullopt; 164*6777b538SAndroid Build Coastguard Worker } 165*6777b538SAndroid Build Coastguard Worker split.category = name.substr(0u, number_loc); 166*6777b538SAndroid Build Coastguard Worker return split; 167*6777b538SAndroid Build Coastguard Worker} 168*6777b538SAndroid Build Coastguard Worker 169*6777b538SAndroid Build Coastguard Worker// static 170*6777b538SAndroid Build Coastguard WorkerSysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() { 171*6777b538SAndroid Build Coastguard Worker HardwareInfo info; 172*6777b538SAndroid Build Coastguard Worker info.manufacturer = "Apple Inc."; 173*6777b538SAndroid Build Coastguard Worker info.model = HardwareModelName(); 174*6777b538SAndroid Build Coastguard Worker DCHECK(IsStringUTF8(info.manufacturer)); 175*6777b538SAndroid Build Coastguard Worker DCHECK(IsStringUTF8(info.model)); 176*6777b538SAndroid Build Coastguard Worker return info; 177*6777b538SAndroid Build Coastguard Worker} 178*6777b538SAndroid Build Coastguard Worker 179*6777b538SAndroid Build Coastguard Worker// static 180*6777b538SAndroid Build Coastguard Workervoid SysInfo::SetCpuSecurityMitigationsEnabled() { 181*6777b538SAndroid Build Coastguard Worker // Setting `g_is_cpu_security_mitigation_enabled_read` after it has been read 182*6777b538SAndroid Build Coastguard Worker // is disallowed because it could indicate that some code got a number of 183*6777b538SAndroid Build Coastguard Worker // processor computed without all the required state. 184*6777b538SAndroid Build Coastguard Worker CHECK(!g_is_cpu_security_mitigation_enabled_read); 185*6777b538SAndroid Build Coastguard Worker 186*6777b538SAndroid Build Coastguard Worker g_is_cpu_security_mitigation_enabled = true; 187*6777b538SAndroid Build Coastguard Worker} 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Worker// static 190*6777b538SAndroid Build Coastguard Workervoid SysInfo::ResetCpuSecurityMitigationsEnabledForTesting() { 191*6777b538SAndroid Build Coastguard Worker g_is_cpu_security_mitigation_enabled_read = false; 192*6777b538SAndroid Build Coastguard Worker g_is_cpu_security_mitigation_enabled = false; 193*6777b538SAndroid Build Coastguard Worker} 194*6777b538SAndroid Build Coastguard Worker 195*6777b538SAndroid Build Coastguard Worker} // namespace base 196