Merge pull request #4667 from babyhuey/feat/libkernel-sysctl-hw-model

feat(libkernel): report hw.model from sysctl
This commit is contained in:
Dean 2026-10-13 17:48:21 +13:00 committed by GitHub
commit 73a5f3a41c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 0 deletions

View File

@ -2,6 +2,9 @@
#include "prx/libkernel/DirectMemory/DirectMemory.hpp"
#include "prx/libkernel/KernelErrors.hpp"
#include <algorithm>
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
#endif
#include <cstddef>
#include <cstdint>
#include <cstring>
@ -41,6 +44,20 @@ int CopyOut(const void* value, std::size_t size, void* oldValue, std::size_t* ol
return 0;
}
std::string HostCpuModel() {
#if defined(__x86_64__) || defined(__i386__)
if (__get_cpuid_max(0x80000000, nullptr) < 0x80000004) return {};
unsigned int brand[12] = {};
for (unsigned int leaf = 0; leaf < 3; ++leaf)
__get_cpuid(0x80000002 + leaf, &brand[leaf * 4], &brand[leaf * 4 + 1], &brand[leaf * 4 + 2], &brand[leaf * 4 + 3]);
std::string model(reinterpret_cast<const char*>(brand), strnlen(reinterpret_cast<const char*>(brand), sizeof(brand)));
model.erase(0, model.find_first_not_of(' '));
return model;
#else
return {};
#endif
}
}
extern "C" {
@ -101,6 +118,15 @@ int APS5_VABI sysctl_nid_postfix(const int* name, std::uint32_t nameLength, void
const int value = static_cast<int>(processors);
return CopyOut(&value, sizeof(value), oldValue, oldLength);
}
if (nameLength == 2 && name[0] == 6 && name[1] == 2) {
if (newValue != nullptr) {
*__error_nid_postfix() = 1;
return -1;
}
static const std::string model = HostCpuModel();
if (model.empty()) throw std::runtime_error(std::string(__func__) + ": the host CPU has no CPUID brand string for hw.model");
return CopyOut(model.c_str(), model.size() + 1, oldValue, oldLength);
}
if (nameLength == 2 && name[0] == 6 && name[1] == 5) {
if (newValue != nullptr) {
*__error_nid_postfix() = 1;
@ -188,6 +214,10 @@ int APS5_VABI sysctlbyname_nid_postfix(const char* name, void* oldValue, std::si
static constexpr int mib[] = {6, 3};
return sysctl_nid_postfix(mib, 2, oldValue, oldLength, newValue, newLength);
}
if (std::strcmp(name, "hw.model") == 0) {
static constexpr int mib[] = {6, 2};
return sysctl_nid_postfix(mib, 2, oldValue, oldLength, newValue, newLength);
}
if (std::strcmp(name, "hw.physmem") == 0) {
static constexpr int mib[] = {6, 5};
return sysctl_nid_postfix(mib, 2, oldValue, oldLength, newValue, newLength);

View File

@ -86,6 +86,26 @@ static void CheckPhysicalMemorySysctl() {
Require(sysctl_nid_postfix(mib, 2, &value, &length, &value, sizeof(value)) == -1 && *__error_nid_postfix() == 1);
Require(sysctlbyname_nid_postfix("hw.physmem", &value, &length, &value, sizeof(value)) == -1 && *__error_nid_postfix() == 1);
}
#if defined(__x86_64__) || defined(__i386__)
static void CheckModelSysctl() {
const int mib[] = {6, 2};
*__error_nid_postfix() = 13;
std::size_t length = 0;
Require(sysctl_nid_postfix(mib, 2, nullptr, &length, nullptr, 0) == 0 && length > 1);
const std::size_t size = length;
char model[128] = {};
length = sizeof(model);
Require(sysctlbyname_nid_postfix("hw.model", model, &length, nullptr, 0) == 0 && length == size);
Require(std::strlen(model) + 1 == size && model[0] != ' ');
Require(*__error_nid_postfix() == 13);
char truncated[4] = {};
length = sizeof(truncated);
Require(sysctl_nid_postfix(mib, 2, truncated, &length, nullptr, 0) == -1 && *__error_nid_postfix() == 12);
Require(length == sizeof(truncated) && std::memcmp(truncated, model, sizeof(truncated)) == 0);
length = sizeof(model);
Require(sysctlbyname_nid_postfix("hw.model", model, &length, model, size) == -1 && *__error_nid_postfix() == 1);
}
#endif
static void CheckMachdepCachelineSizeSysctl() {
*__error_nid_postfix() = 13;
int value = 0x5a5a5a5a;
@ -232,6 +252,9 @@ static void CheckArandomSysctl() {
int main() {
CheckProcessorCountSysctl();
CheckPhysicalMemorySysctl();
#if defined(__x86_64__) || defined(__i386__)
CheckModelSysctl();
#endif
CheckMachdepCachelineSizeSysctl();
CheckPathnameSysctl();
CheckSystemSwVersion();

View File

@ -133,6 +133,7 @@
- [execv](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) throws: replacing the process image is not supported, the same as `execvp`. PPSA97358 imports it and fails to load without it.
- [kern.proc.pathname](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) returns `/app0/eboot.bin` for pid -1 and the calling process, following FreeBSD's `sysctl_kern_proc_pathname`; the exact pathname on retail consoles remains unverified.
- [machdep.cacheline_size](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) returns -1 with `ENOENT`, matching FreeBSD amd64 where this sysctl OID is not defined.
- [hw.model](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) reports the host CPU's name, built as FreeBSD 11 builds `hw.model`: the CPUID brand string (leaves 0x80000002 to 0x80000004) without leading spaces ([identcpu.c](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/x86/x86/identcpu.c#L683-L691)). Trailing padding stays, as it does there, so an AMD host's name ends in spaces. The name a PS5 reports is unknown. A write returns -1 with `EPERM`. A host without an x86 CPUID brand string, such as an Apple Silicon Mac, throws. PPSA99203 only prints it (`[console] hw.model: %s`)
- [getrlimit](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - `RLIMIT_CPU`, `RLIMIT_FSIZE`, `RLIMIT_CORE`, `RLIMIT_SBSIZE`, `RLIMIT_VMEM`/`AS`, `RLIMIT_NPTS`, `RLIMIT_SWAP`, `RLIMIT_KQUEUES` and `RLIMIT_UMTXP` report infinity as in FreeBSD's process-0 defaults, and `RLIMIT_DATA` mirrors the host limit. `RLIMIT_STACK`, `RLIMIT_RSS`, `RLIMIT_MEMLOCK`, `RLIMIT_NPROC` and `RLIMIT_NOFILE` throw because no console values are established.
- [setrlimit](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) validates the resource and input in FreeBSD order, maps negative limits to infinity, and lowers a soft limit above the hard limit. A request succeeds only when its normalized values match `getrlimit`; changing limits throws because guest limit state is not stored.
- [execvp](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) throws: replacing the process image is not supported. PPSA85300 imports it and fails to load without it; its `fork` and `vfork` fail with `ENOSYS` ([libc_missing.c](https://github.com/ZiZc3/VLC/blob/f3253020a64368153233ede29183014c0b6c8979/ps5/compat/libc_missing.c#L290-L292)), so the child process that would call it is never created.