|
@@ -118,27 +118,49 @@ static struct cachepolicy cache_policies[] __initdata = {
|
|
|
|
|
|
#ifdef CONFIG_CPU_CP15
|
|
|
/*
|
|
|
- * These are useful for identifying cache coherency
|
|
|
- * problems by allowing the cache or the cache and
|
|
|
- * writebuffer to be turned off. (Note: the write
|
|
|
- * buffer should not be on and the cache off).
|
|
|
+ * Initialise the cache_policy variable with the initial state specified
|
|
|
+ * via the "pmd" value. This is used to ensure that on ARMv6 and later,
|
|
|
+ * the C code sets the page tables up with the same policy as the head
|
|
|
+ * assembly code, which avoids an illegal state where the TLBs can get
|
|
|
+ * confused. See comments in early_cachepolicy() for more information.
|
|
|
*/
|
|
|
-static int __init early_cachepolicy(char *p)
|
|
|
+void __init init_default_cache_policy(unsigned long pmd)
|
|
|
{
|
|
|
- unsigned long cr = get_cr();
|
|
|
int i;
|
|
|
|
|
|
+ pmd &= PMD_SECT_TEX(1) | PMD_SECT_BUFFERABLE | PMD_SECT_CACHEABLE;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(cache_policies); i++)
|
|
|
+ if (cache_policies[i].pmd == pmd) {
|
|
|
+ cachepolicy = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == ARRAY_SIZE(cache_policies))
|
|
|
+ pr_err("ERROR: could not find cache policy\n");
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * These are useful for identifying cache coherency problems by allowing
|
|
|
+ * the cache or the cache and writebuffer to be turned off. (Note: the
|
|
|
+ * write buffer should not be on and the cache off).
|
|
|
+ */
|
|
|
+static int __init early_cachepolicy(char *p)
|
|
|
+{
|
|
|
+ int i, selected = -1;
|
|
|
+
|
|
|
for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
|
|
|
int len = strlen(cache_policies[i].policy);
|
|
|
|
|
|
if (memcmp(p, cache_policies[i].policy, len) == 0) {
|
|
|
- cachepolicy = i;
|
|
|
- cr = __clear_cr(cache_policies[i].cr_mask);
|
|
|
+ selected = i;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- if (i == ARRAY_SIZE(cache_policies))
|
|
|
- printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
|
|
|
+
|
|
|
+ if (selected == -1)
|
|
|
+ pr_err("ERROR: unknown or unsupported cache policy\n");
|
|
|
+
|
|
|
/*
|
|
|
* This restriction is partly to do with the way we boot; it is
|
|
|
* unpredictable to have memory mapped using two different sets of
|
|
@@ -146,12 +168,18 @@ static int __init early_cachepolicy(char *p)
|
|
|
* change these attributes once the initial assembly has setup the
|
|
|
* page tables.
|
|
|
*/
|
|
|
- if (cpu_architecture() >= CPU_ARCH_ARMv6) {
|
|
|
- printk(KERN_WARNING "Only cachepolicy=writeback supported on ARMv6 and later\n");
|
|
|
- cachepolicy = CPOLICY_WRITEBACK;
|
|
|
+ if (cpu_architecture() >= CPU_ARCH_ARMv6 && selected != cachepolicy) {
|
|
|
+ pr_warn("Only cachepolicy=%s supported on ARMv6 and later\n",
|
|
|
+ cache_policies[cachepolicy].policy);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selected != cachepolicy) {
|
|
|
+ unsigned long cr = __clear_cr(cache_policies[selected].cr_mask);
|
|
|
+ cachepolicy = selected;
|
|
|
+ flush_cache_all();
|
|
|
+ set_cr(cr);
|
|
|
}
|
|
|
- flush_cache_all();
|
|
|
- set_cr(cr);
|
|
|
return 0;
|
|
|
}
|
|
|
early_param("cachepolicy", early_cachepolicy);
|
|
@@ -385,8 +413,11 @@ static void __init build_mem_type_table(void)
|
|
|
cachepolicy = CPOLICY_WRITEBACK;
|
|
|
ecc_mask = 0;
|
|
|
}
|
|
|
- if (is_smp())
|
|
|
+
|
|
|
+ if (is_smp() && cachepolicy != CPOLICY_WRITEALLOC) {
|
|
|
+ pr_warn("Forcing write-allocate cache policy for SMP\n");
|
|
|
cachepolicy = CPOLICY_WRITEALLOC;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* Strip out features not present on earlier architectures.
|