summaryrefslogtreecommitdiffstats
path: root/sys/arm/arm
diff options
context:
space:
mode:
authormmel <mmel@FreeBSD.org>2017-06-13 12:07:18 +0000
committerLuiz Souza <luiz@netgate.com>2017-09-06 12:34:43 -0500
commitd2b2169803329131e3defcc0e636a53ec231456e (patch)
treea76b363b353f7bfa0d608b6adc0f36caccdb3401 /sys/arm/arm
parente38b0f53cd4363294f7f0b7d0fe43192c1c8801a (diff)
downloadFreeBSD-src-d2b2169803329131e3defcc0e636a53ec231456e.zip
FreeBSD-src-d2b2169803329131e3defcc0e636a53ec231456e.tar.gz
Implement tunable CPU quirks.
These quirks are intended for optimizing CPU performance, not for applying errata workarounds. Nobody can expect that CPU with unfixed errata is stable enough to execute the kernel until quirks are applied. MFC after: 3 weeks (cherry picked from commit 1065b8567421165a5e65e3ad5d8fa4bc348efdea)
Diffstat (limited to 'sys/arm/arm')
-rw-r--r--sys/arm/arm/cpuinfo.c48
-rw-r--r--sys/arm/arm/mp_machdep.c4
-rw-r--r--sys/arm/arm/pmap-v6.c5
3 files changed, 50 insertions, 7 deletions
diff --git a/sys/arm/arm/cpuinfo.c b/sys/arm/arm/cpuinfo.c
index 8099882..74c5f3d 100644
--- a/sys/arm/arm/cpuinfo.c
+++ b/sys/arm/arm/cpuinfo.c
@@ -30,10 +30,15 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <machine/cpu.h>
#include <machine/cpuinfo.h>
+#if __ARM_ARCH >= 6
+void reinit_mmu(uint32_t ttb, uint32_t aux_clr, uint32_t aux_set);
+#endif
+
struct cpuinfo cpuinfo =
{
/* Use safe defaults for start */
@@ -43,6 +48,30 @@ struct cpuinfo cpuinfo =
.icache_line_mask = 31,
};
+static SYSCTL_NODE(_hw, OID_AUTO, cpu, CTLFLAG_RD, 0,
+ "CPU");
+static SYSCTL_NODE(_hw_cpu, OID_AUTO, quirks, CTLFLAG_RD, 0,
+ "CPU quirks");
+
+/*
+ * Tunable CPU quirks.
+ * Be careful, ACTRL cannot be changed if CPU is started in secure
+ * mode(world) and write to ACTRL can cause exception!
+ * These quirks are intended for optimizing CPU performance, not for
+ * applying errata workarounds. Nobody can expect that CPU with unfixed
+ * errata is stable enough to execute the kernel until quirks are applied.
+ */
+static uint32_t cpu_quirks_actlr_mask;
+SYSCTL_INT(_hw_cpu_quirks, OID_AUTO, actlr_mask,
+ CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &cpu_quirks_actlr_mask, 0,
+ "Bits to be masked in ACTLR");
+
+static uint32_t cpu_quirks_actlr_set;
+SYSCTL_INT(_hw_cpu_quirks, OID_AUTO, actlr_set,
+ CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &cpu_quirks_actlr_set, 0,
+ "Bits to be set in ACTLR");
+
+
/* Read and parse CPU id scheme */
void
cpuinfo_init(void)
@@ -153,15 +182,17 @@ cpuinfo_init(void)
#endif
}
+#if __ARM_ARCH >= 6
/*
* Get bits that must be set or cleared in ACLR register.
* Note: Bits in ACLR register are IMPLEMENTATION DEFINED.
* Its expected that SCU is in operational state before this
* function is called.
*/
-void
+static void
cpuinfo_get_actlr_modifier(uint32_t *actlr_mask, uint32_t *actlr_set)
{
+
*actlr_mask = 0;
*actlr_set = 0;
@@ -236,3 +267,18 @@ cpuinfo_get_actlr_modifier(uint32_t *actlr_mask, uint32_t *actlr_set)
return;
}
}
+
+/* Reinitialize MMU to final kernel mapping and apply all CPU quirks. */
+void
+cpuinfo_reinit_mmu(uint32_t ttb)
+{
+ uint32_t actlr_mask;
+ uint32_t actlr_set;
+
+ cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set);
+ actlr_mask |= cpu_quirks_actlr_mask;
+ actlr_set |= cpu_quirks_actlr_set;
+ reinit_mmu(ttb, actlr_mask, actlr_set);
+}
+
+#endif /* __ARM_ARCH >= 6 */
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index 2dc7171..ae3d724 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -155,11 +155,9 @@ init_secondary(int cpu)
#ifndef INTRNG
int start = 0, end = 0;
#endif
- uint32_t actlr_mask, actlr_set;
pmap_set_tex();
- cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set);
- reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set);
+ cpuinfo_reinit_mmu(pmap_kern_ttb);
cpu_setup();
/* Provide stack pointers for other processor modes. */
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index 3f41192..6d11fcf 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -762,7 +762,7 @@ pmap_bootstrap_prepare(vm_paddr_t last)
pt1_entry_t *pte1p;
pt2_entry_t *pte2p;
u_int i;
- uint32_t actlr_mask, actlr_set, l1_attr;
+ uint32_t l1_attr;
/*
* Now, we are going to make real kernel mapping. Note that we are
@@ -879,8 +879,7 @@ pmap_bootstrap_prepare(vm_paddr_t last)
/* Finally, switch from 'boot_pt1' to 'kern_pt1'. */
pmap_kern_ttb = base_pt1 | ttb_flags;
- cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set);
- reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set);
+ cpuinfo_reinit_mmu(pmap_kern_ttb);
/*
* Initialize the first available KVA. As kernel image is mapped by
* sections, we are leaving some gap behind.
OpenPOWER on IntegriCloud