new file mode 100644
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_SHMPARAM_H
+#define _ASM_RISCV_SHMPARAM_H
+
+/*
+ * Minimum alignment of shared memory segments as a function of cache geometry.
+ */
+#define SHMLBA arch_shmlba()
+
+long arch_shmlba(void);
+
+#endif /* _ASM_RISCV_SHMPARAM_H */
@@ -1,12 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017 SiFive
+ * Copyright (C) 2019 Aril Inc
*/
#include <linux/cacheinfo.h>
#include <linux/cpu.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/mm.h>
+
+static long shmlba;
+
+
+/*
+ * Assuming cache size = line size * #sets * N for N-way associative caches,
+ * return the max cache "span" == (line size * #sets) == (cache size / N)
+ * across all L1 caches, or 0 if cache parameters are not available.
+ * VIPT caches with span > min page size are susceptible to aliasing.
+ */
+static long get_max_cache_span(void)
+{
+ struct cpu_cacheinfo *this_cpu_ci;
+ struct cacheinfo *this_leaf;
+ long span, max_span = 0;
+ int cpu, leaf;
+
+ for_each_possible_cpu(cpu) {
+ this_cpu_ci = get_cpu_cacheinfo(cpu);
+ this_leaf = this_cpu_ci->info_list;
+ for (leaf = 0; leaf < this_cpu_ci->num_leaves; leaf++, this_leaf++) {
+ if (this_leaf->level > 1)
+ break;
+ span = this_leaf->coherency_line_size * this_leaf->number_of_sets;
+ if (span > max_span)
+ max_span = span;
+ }
+ }
+ return max_span;
+}
+
+/*
+ * Align shared mappings to the maximum cache "span" to avoid aliasing
+ * in VIPT caches, for performance.
+ * The returned SHMLBA value is always a power-of-two multiple of PAGE_SIZE.
+ */
+long arch_shmlba(void)
+{
+ if (shmlba == 0) {
+ long max_span = get_max_cache_span();
+ shmlba = max_span ? PAGE_ALIGN(max_span) : 4 * PAGE_SIZE;
+ }
+ return shmlba;
+}
static void ci_leaf_init(struct cacheinfo *this_leaf,
struct device_node *node,
@@ -93,6 +139,9 @@ static int __populate_cache_leaves(unsigned int cpu)
}
of_node_put(np);
+ /* Force recalculating SHMLBA if cache parameters are updated. */
+ shmlba = 0;
+
return 0;
}
Set SHMLBA to the maximum cache "span" (line size * number of sets) of all CPU L1 instruction and data caches (L2 and up are rarely VIPT). This avoids VIPT cache aliasing with minimal alignment constraints. If the device tree does not provide cache parameters, use a conservative default of 16 KB: only large enough to avoid aliasing in most VIPT caches. Signed-off-by: Marc Gauthier <consult-mg@gstardust.com> --- arch/riscv/include/asm/shmparam.h | 12 ++++++++ arch/riscv/kernel/cacheinfo.c | 49 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 arch/riscv/include/asm/shmparam.h