1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017 SiFive
6 #include <linux/acpi.h>
8 #include <linux/prctl.h>
10 #include <asm/cacheflush.h>
16 static void ipi_remote_fence_i(void *info
)
18 return local_flush_icache_all();
21 void flush_icache_all(void)
23 local_flush_icache_all();
25 if (num_online_cpus() < 2)
27 else if (riscv_use_sbi_for_rfence())
28 sbi_remote_fence_i(NULL
);
30 on_each_cpu(ipi_remote_fence_i
, NULL
, 1);
32 EXPORT_SYMBOL(flush_icache_all
);
35 * Performs an icache flush for the given MM context. RISC-V has no direct
36 * mechanism for instruction cache shoot downs, so instead we send an IPI that
37 * informs the remote harts they need to flush their local instruction caches.
38 * To avoid pathologically slow behavior in a common case (a bunch of
39 * single-hart processes on a many-hart machine, ie 'make -j') we avoid the
40 * IPIs for harts that are not currently executing a MM context and instead
41 * schedule a deferred local instruction cache flush to be performed before
42 * execution resumes on each hart.
44 void flush_icache_mm(struct mm_struct
*mm
, bool local
)
47 cpumask_t others
, *mask
;
51 /* Mark every hart's icache as needing a flush for this MM. */
52 mask
= &mm
->context
.icache_stale_mask
;
54 /* Flush this hart's I$ now, and mark it as flushed. */
55 cpu
= smp_processor_id();
56 cpumask_clear_cpu(cpu
, mask
);
57 local_flush_icache_all();
60 * Flush the I$ of other harts concurrently executing, and mark them as
63 cpumask_andnot(&others
, mm_cpumask(mm
), cpumask_of(cpu
));
64 local
|= cpumask_empty(&others
);
65 if (mm
== current
->active_mm
&& local
) {
67 * It's assumed that at least one strongly ordered operation is
68 * performed on this hart between setting a hart's cpumask bit
69 * and scheduling this MM context on that hart. Sending an SBI
70 * remote message will do this, but in the case where no
71 * messages are sent we still need to order this hart's writes
72 * with flush_icache_deferred().
75 } else if (riscv_use_sbi_for_rfence()) {
76 sbi_remote_fence_i(&others
);
78 on_each_cpu_mask(&others
, ipi_remote_fence_i
, NULL
, 1);
84 #endif /* CONFIG_SMP */
87 void flush_icache_pte(struct mm_struct
*mm
, pte_t pte
)
89 struct folio
*folio
= page_folio(pte_page(pte
));
91 if (!test_bit(PG_dcache_clean
, &folio
->flags
)) {
92 flush_icache_mm(mm
, false);
93 set_bit(PG_dcache_clean
, &folio
->flags
);
96 #endif /* CONFIG_MMU */
98 unsigned int riscv_cbom_block_size
;
99 EXPORT_SYMBOL_GPL(riscv_cbom_block_size
);
101 unsigned int riscv_cboz_block_size
;
102 EXPORT_SYMBOL_GPL(riscv_cboz_block_size
);
104 static void __init
cbo_get_block_size(struct device_node
*node
,
105 const char *name
, u32
*block_size
,
106 unsigned long *first_hartid
)
108 unsigned long hartid
;
111 if (riscv_of_processor_hartid(node
, &hartid
))
114 if (of_property_read_u32(node
, name
, &val
))
119 *first_hartid
= hartid
;
120 } else if (*block_size
!= val
) {
121 pr_warn("%s mismatched between harts %lu and %lu\n",
122 name
, *first_hartid
, hartid
);
126 void __init
riscv_init_cbo_blocksizes(void)
128 unsigned long cbom_hartid
, cboz_hartid
;
129 u32 cbom_block_size
= 0, cboz_block_size
= 0;
130 struct device_node
*node
;
131 struct acpi_table_header
*rhct
;
135 for_each_of_cpu_node(node
) {
136 /* set block-size for cbom and/or cboz extension if available */
137 cbo_get_block_size(node
, "riscv,cbom-block-size",
138 &cbom_block_size
, &cbom_hartid
);
139 cbo_get_block_size(node
, "riscv,cboz-block-size",
140 &cboz_block_size
, &cboz_hartid
);
143 status
= acpi_get_table(ACPI_SIG_RHCT
, 0, &rhct
);
144 if (ACPI_FAILURE(status
))
147 acpi_get_cbo_block_size(rhct
, &cbom_block_size
, &cboz_block_size
, NULL
);
148 acpi_put_table((struct acpi_table_header
*)rhct
);
152 riscv_cbom_block_size
= cbom_block_size
;
155 riscv_cboz_block_size
= cboz_block_size
;
159 static void set_icache_stale_mask(void)
166 * Mark every other hart's icache as needing a flush for
167 * this MM. Maintain the previous value of the current
168 * cpu to handle the case when this function is called
169 * concurrently on different harts.
171 mask
= ¤t
->mm
->context
.icache_stale_mask
;
172 stale_cpu
= cpumask_test_cpu(cpu
, mask
);
174 cpumask_setall(mask
);
175 cpumask_assign_cpu(cpu
, mask
, stale_cpu
);
181 * riscv_set_icache_flush_ctx() - Enable/disable icache flushing instructions in
183 * @ctx: Set the type of icache flushing instructions permitted/prohibited in
184 * userspace. Supported values described below.
186 * Supported values for ctx:
188 * * %PR_RISCV_CTX_SW_FENCEI_ON: Allow fence.i in user space.
190 * * %PR_RISCV_CTX_SW_FENCEI_OFF: Disallow fence.i in user space. All threads in
191 * a process will be affected when ``scope == PR_RISCV_SCOPE_PER_PROCESS``.
192 * Therefore, caution must be taken; use this flag only when you can guarantee
193 * that no thread in the process will emit fence.i from this point onward.
195 * @scope: Set scope of where icache flushing instructions are allowed to be
196 * emitted. Supported values described below.
198 * Supported values for scope:
200 * * %PR_RISCV_SCOPE_PER_PROCESS: Ensure the icache of any thread in this process
201 * is coherent with instruction storage upon
204 * * %PR_RISCV_SCOPE_PER_THREAD: Ensure the icache of the current thread is
205 * coherent with instruction storage upon
208 * When ``scope == PR_RISCV_SCOPE_PER_PROCESS``, all threads in the process are
209 * permitted to emit icache flushing instructions. Whenever any thread in the
210 * process is migrated, the corresponding hart's icache will be guaranteed to be
211 * consistent with instruction storage. This does not enforce any guarantees
212 * outside of migration. If a thread modifies an instruction that another thread
213 * may attempt to execute, the other thread must still emit an icache flushing
214 * instruction before attempting to execute the potentially modified
215 * instruction. This must be performed by the user-space program.
217 * In per-thread context (eg. ``scope == PR_RISCV_SCOPE_PER_THREAD``) only the
218 * thread calling this function is permitted to emit icache flushing
219 * instructions. When the thread is migrated, the corresponding hart's icache
220 * will be guaranteed to be consistent with instruction storage.
222 * On kernels configured without SMP, this function is a nop as migrations
223 * across harts will not occur.
225 int riscv_set_icache_flush_ctx(unsigned long ctx
, unsigned long scope
)
229 case PR_RISCV_CTX_SW_FENCEI_ON
:
231 case PR_RISCV_SCOPE_PER_PROCESS
:
232 current
->mm
->context
.force_icache_flush
= true;
234 case PR_RISCV_SCOPE_PER_THREAD
:
235 current
->thread
.force_icache_flush
= true;
241 case PR_RISCV_CTX_SW_FENCEI_OFF
:
243 case PR_RISCV_SCOPE_PER_PROCESS
:
244 set_icache_stale_mask();
245 current
->mm
->context
.force_icache_flush
= false;
247 case PR_RISCV_SCOPE_PER_THREAD
:
248 set_icache_stale_mask();
249 current
->thread
.force_icache_flush
= false;
261 case PR_RISCV_CTX_SW_FENCEI_ON
:
262 case PR_RISCV_CTX_SW_FENCEI_OFF
: