aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeandro Lupori <luporl@FreeBSD.org>2021-09-15 18:12:37 +0000
committerLeandro Lupori <luporl@FreeBSD.org>2021-09-30 11:34:16 +0000
commitcc8e726c85bee3f3da0fb02c12028f2310a7ee17 (patch)
tree0320f0717fc28316e5abdc6ac3291035cb19fade
parentc926cf71d4445575069214881bf13bdeb4a6a6d1 (diff)
downloadsrc-cc8e726c85bee3f3da0fb02c12028f2310a7ee17.tar.gz
src-cc8e726c85bee3f3da0fb02c12028f2310a7ee17.zip
powerpc64: change CAS to support Radix MMU
Use radix_mmu environment variable to select between Hash or Radix MMU, when performing the CAS method call. This matches kernel's behavior, by selecting Hash MMU by default and Radix if radix_mmu is not zero, to make sure that both loader and kernel always select the same MMU. The device tree is queried to detect Radix/GTSE support and to find out if CAS is supported, making the old CPU version and HV bit checks unnecessary now. Reviewed by: jhibbits Sponsored by: Instituto de Pesquisas Eldorado (eldorado.org.br) Differential Revision: https://reviews.freebsd.org/D31951 (cherry picked from commit a58abcde2c83b71e5bf19575750564f7bff78833)
-rw-r--r--stand/powerpc/ofw/cas.c120
1 files changed, 74 insertions, 46 deletions
diff --git a/stand/powerpc/ofw/cas.c b/stand/powerpc/ofw/cas.c
index 96d276386b71..4f36a147f36d 100644
--- a/stand/powerpc/ofw/cas.c
+++ b/stand/powerpc/ofw/cas.c
@@ -29,6 +29,13 @@ __FBSDID("$FreeBSD$");
#include <openfirm.h>
#include <stand.h>
+/* #define CAS_DEBUG */
+#ifdef CAS_DEBUG
+#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...) do { ; } while (0)
+#endif
+
/* PVR */
#define PVR_CPU_P8E 0x004b0000
#define PVR_CPU_P8NVL 0x004c0000
@@ -83,13 +90,19 @@ __FBSDID("$FreeBSD$");
#define OV5_INTC_XICS 0
/* byte 24: MMU */
+#define OV5_MMU_INDEX 24
#define OV5_MMU_HPT 0
+#define OV5_MMU_RADIX 0x40
+#define OV5_MMU_EITHER 0x80
+#define OV5_MMU_DYNAMIC 0xc0
/* byte 25: HPT MMU Extensions */
-#define OV5_HPT_EXT_NONE 0
+#define OV5_HPT_EXT_INDEX 25
+#define OV5_HPT_GTSE 0x40
/* byte 26: Radix MMU Extensions */
-#define OV5_RPT_EXT_NONE 0
+#define OV5_RADIX_EXT_INDEX 26
+#define OV5_RADIX_GTSE 0x40
struct pvr {
@@ -163,69 +176,84 @@ static struct ibm_arch_vec {
0, /* DRMEM_V2 */
OV5_INTC_XICS,
OV5_MMU_HPT,
- OV5_HPT_EXT_NONE,
- OV5_RPT_EXT_NONE
+ 0,
+ 0
}
};
-static __inline register_t
-mfpvr(void)
-{
- register_t value;
-
- __asm __volatile ("mfpvr %0" : "=r"(value));
-
- return (value);
-}
-
-static __inline int
-ppc64_hv(void)
-{
- int hv;
-
- /* PSL_HV is bit 3 of 64-bit MSR */
- __asm __volatile ("mfmsr %0\n\t"
- "rldicl %0,%0,4,63" : "=r"(hv));
-
- return (hv);
-}
-
int
ppc64_cas(void)
{
- int rc;
- ihandle_t ihandle;
+ phandle_t pkg;
+ ihandle_t inst;
cell_t err;
+ uint8_t buf[16], idx, val;
+ int i, len, rc, radix_mmu;
+ const char *var;
+ char *ov5;
+
+ pkg = OF_finddevice("/chosen");
+ if (pkg == -1) {
+ printf("cas: couldn't find /chosen\n");
+ return (-1);
+ }
+
+ len = OF_getprop(pkg, "ibm,arch-vec-5-platform-support", buf,
+ sizeof(buf));
+ if (len == -1)
+ /* CAS not supported */
+ return (0);
- /* Perform CAS only for POWER8 and later cores */
- switch (mfpvr() & PVR_CPU_MASK) {
- case PVR_CPU_P8:
- case PVR_CPU_P8E:
- case PVR_CPU_P8NVL:
- case PVR_CPU_P9:
+ radix_mmu = 0;
+ ov5 = ibm_arch_vec.vec5.data;
+ for (i = 0; i < len; i += 2) {
+ idx = buf[i];
+ val = buf[i + 1];
+ DPRINTF("idx 0x%02x val 0x%02x\n", idx, val);
+
+ switch (idx) {
+ case OV5_MMU_INDEX:
+ /*
+ * Note that testing for OV5_MMU_RADIX/OV5_MMU_EITHER
+ * also covers OV5_MMU_DYNAMIC.
+ */
+ if ((val & OV5_MMU_RADIX) || (val & OV5_MMU_EITHER))
+ radix_mmu = 1;
break;
+
+ case OV5_RADIX_EXT_INDEX:
+ if (val & OV5_RADIX_GTSE)
+ ov5[idx] = OV5_RADIX_GTSE;
+ break;
+
+ case OV5_HPT_EXT_INDEX:
default:
- return (0);
+ break;
+ }
}
- /* Skip CAS when running on PowerNV */
- if (ppc64_hv())
- return (0);
+ if (radix_mmu && (var = getenv("radix_mmu")) != NULL && var[0] != '0')
+ ov5[OV5_MMU_INDEX] = OV5_MMU_RADIX;
+ else
+ radix_mmu = 0;
- ihandle = OF_open("/");
- if (ihandle == -1) {
+ inst = OF_open("/");
+ if (inst == -1) {
printf("cas: failed to open / node\n");
return (-1);
}
- if (rc = OF_call_method("ibm,client-architecture-support",
- ihandle, 1, 1, &ibm_arch_vec, &err))
- printf("cas: failed to call CAS method\n");
- else if (err) {
- printf("cas: error: 0x%08lX\n", err);
+ DPRINTF("MMU 0x%02x RADIX_EXT 0x%02x\n",
+ ov5[OV5_MMU_INDEX], ov5[OV5_RADIX_EXT_INDEX]);
+ rc = OF_call_method("ibm,client-architecture-support",
+ inst, 1, 1, &ibm_arch_vec, &err);
+ if (rc != 0 || err) {
+ printf("cas: CAS method returned an error: rc %d err %jd\n",
+ rc, (intmax_t)err);
rc = -1;
}
- OF_close(ihandle);
+ OF_close(inst);
+ printf("cas: selected %s MMU\n", radix_mmu ? "radix" : "hash");
return (rc);
}