Merge pull request #4667 from babyhuey/feat/libkernel-sysctl-hw-model
feat(libkernel): report hw.model from sysctl
This commit is contained in:
commit
73a5f3a41c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue