On 6/10/26 20:49, Richard Henderson wrote:
On 6/10/26 11:06, Helge Deller wrote:
From: Helge Deller <[email protected]>
I've tried to mimic what I've seen on two debian porterboxes (ppc64 and
ppc64le), which are running via KVM/QEMU. I assume the model type of
pSeries and such doesn't make much sense for some older ppc chips, so
any better suggestions here are welcome.
v2: drop colon, add clock output, refine pvr calculation
(@Richard: I suggest to completely drop the clock for v3 ?!?!)
Signed-off-by: Helge Deller <[email protected]>
Cc: [email protected]
Cc: Richard Henderson <[email protected]>
---
linux-user/ppc/target_proc.h | 91 +++++++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 1 deletion(-)
diff --git a/linux-user/ppc/target_proc.h b/linux-user/ppc/target_proc.h
index 43fe29ca72..6d78c0f543 100644
--- a/linux-user/ppc/target_proc.h
+++ b/linux-user/ppc/target_proc.h
@@ -1 +1,90 @@
-/* No target-specific /proc support */
+/*
+ * ppc specific proc functions for linux-user
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef PPC_TARGET_PROC_H
+#define PPC_TARGET_PROC_H
+
+#include <time.h>
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+ struct timespec res;
+ double freq_mhz;
+ int i, num_cpus;
+ unsigned int maj, min, pvr;
+
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(env_cpu(cpu_env));
+ DeviceClass *dc = DEVICE_CLASS(ppc_cpu_get_family_class(pcc));
+
+ pvr = pcc->pvr;
+
+ /* Taken from Linux kernel: */
+ /* If we are a Freescale core do a simple check so
+ * we don't have to keep adding cases in the future */
+ if (PVR_VER(pvr) & 0x8000) {
+ switch (PVR_VER(pvr)) {
+ case 0x8000: /* 7441/7450/7451, Voyager */
+ case 0x8001: /* 7445/7455, Apollo 6 */
+ case 0x8002: /* 7447/7457, Apollo 7 */
+ case 0x8003: /* 7447A, Apollo 7 PM */
+ case 0x8004: /* 7448, Apollo 8 */
+ case 0x800c: /* 7410, Nitro */
+ maj = ((pvr >> 8) & 0xF);
+ min = PVR_MIN(pvr);
+ break;
+ default: /* e500/book-e */
+ maj = PVR_MAJ(pvr);
+ min = PVR_MIN(pvr);
+ break;
+ }
+ } else {
+ switch (PVR_VER(pvr)) {
+ case 0x1008: /* 740P/750P ?? */
+ maj = ((pvr >> 8) & 0xFF) - 1;
+ min = pvr & 0xFF;
+ break;
+ case 0x004e: /* POWER9 bits 12-15 give chip type */
+ case 0x0080: /* POWER10 bit 12 gives SMT8/4 */
+ maj = (pvr >> 8) & 0x0F;
+ min = pvr & 0xFF;
+ break;
+ default:
+ maj = (pvr >> 8) & 0xFF;
+ min = pvr & 0xFF;
+ break;
+ }
+ }
Reindent for qemu style.
Sure, will do.
+ if (clock_getres(CLOCK_REALTIME, &res) == -1) {
+ res.tv_nsec = 1;
+ }
+ freq_mhz = 1000.0 / res.tv_nsec;
Seems ok.
Yes. But it will allways print 1000.000MHz, which isn't that useful either.
Shall I keep it nevertheless?
+ dprintf(fd, "processor:\t: %d\n", i);
Still have an extra : here.
Sigh :-)
Will fix.
Helge