2 * ARC700 VIPT Cache Management
4 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs
11 * -flush_cache_dup_mm (fork)
12 * -likewise for flush_cache_mm (exit/execve)
13 * -likewise for flush_cache_range,flush_cache_page (munmap, exit, COW-break)
16 * -Now that MMU can support larger pg sz (16K), the determiniation of
17 * aliasing shd not be based on assumption of 8k pg
20 * -optimised version of flush_icache_range( ) for making I/D coherent
21 * when vaddr is available (agnostic of num of aliases)
24 * -Added documentation about I-cache aliasing on ARC700 and the way it
25 * was handled up until MMU V2.
26 * -Spotted a three year old bug when killing the 4 aliases, which needs
27 * bottom 2 bits, so we need to do paddr | {0x00, 0x01, 0x02, 0x03}
28 * instead of paddr | {0x00, 0x01, 0x10, 0x11}
29 * (Rajesh you owe me one now)
32 * -Off-by-one error when computing num_of_lines to flush
33 * This broke signal handling with bionic which uses synthetic sigret stub
36 * -GCC can't generate ZOL for core cache flush loops.
37 * Conv them into iterations based as opposed to while (start < end) types
40 * -In I-cache flush routine we used to chk for aliasing for every line INV.
41 * Instead now we setup routines per cache geometry and invoke them
42 * via function pointers.
45 * -Cache Line flush routines used to flush an extra line beyond end addr
46 * because check was while (end >= start) instead of (end > start)
47 * =Some call sites had to work around by doing -1, -4 etc to end param
48 * =Some callers didnt care. This was spec bad in case of INV routines
49 * which would discard valid data (cause of the horrible ext2 bug
52 * vineetg: June 11th 2008: Fixed flush_icache_range( )
53 * -Since ARC700 caches are not coherent (I$ doesnt snoop D$) both need
54 * to be flushed, which it was not doing.
55 * -load_module( ) passes vmalloc addr (Kernel Virtual Addr) to the API,
56 * however ARC cache maintenance OPs require PHY addr. Thus need to do
58 * -Also added optimisation there, that for range > PAGE SIZE we flush the
59 * entire cache in one shot rather than line by line. For e.g. a module
60 * with Code sz 600k, old code flushed 600k worth of cache (line-by-line),
61 * while cache is only 16 or 32k.
64 #include <linux/module.h>
66 #include <linux/sched.h>
67 #include <linux/cache.h>
68 #include <linux/mmu_context.h>
69 #include <linux/syscalls.h>
70 #include <linux/uaccess.h>
71 #include <asm/cacheflush.h>
72 #include <asm/cachectl.h>
73 #include <asm/setup.h>
76 #ifdef CONFIG_ARC_HAS_ICACHE
77 static void __ic_line_inv_no_alias(unsigned long, int);
78 static void __ic_line_inv_2_alias(unsigned long, int);
79 static void __ic_line_inv_4_alias(unsigned long, int);
81 /* Holds the ptr to flush routine, dependign on size due to aliasing issues */
82 static void (*___flush_icache_rtn) (unsigned long, int);
86 * Read the Cache Build Confuration Registers, Decode them and save into
87 * the cpuinfo structure for later use.
88 * No Validation done here, simply read/convert the BCRs
90 void __init read_decode_cache_bcr(void)
92 struct bcr_cache ibcr, dbcr;
93 struct cpuinfo_arc_cache *p_ic, *p_dc;
94 unsigned int cpu = smp_processor_id();
96 p_ic = &cpuinfo_arc700[cpu].icache;
97 READ_BCR(ARC_REG_IC_BCR, ibcr);
99 if (ibcr.config == 0x3)
101 p_ic->line_len = 8 << ibcr.line_len;
102 p_ic->sz = 0x200 << ibcr.sz;
103 p_ic->ver = ibcr.ver;
105 p_dc = &cpuinfo_arc700[cpu].dcache;
106 READ_BCR(ARC_REG_DC_BCR, dbcr);
108 if (dbcr.config == 0x2)
110 p_dc->line_len = 16 << dbcr.line_len;
111 p_dc->sz = 0x200 << dbcr.sz;
112 p_dc->ver = dbcr.ver;
116 * 1. Validate the Cache Geomtery (compile time config matches hardware)
117 * 2. If I-cache suffers from aliasing, setup work arounds (difft flush rtn)
118 * (aliasing D-cache configurations are not supported YET)
119 * 3. Enable the Caches, setup default flush mode for D-Cache
120 * 3. Calculate the SHMLBA used by user space
122 void __init arc_cache_init(void)
125 #ifdef CONFIG_ARC_CACHE
126 unsigned int cpu = smp_processor_id();
128 #ifdef CONFIG_ARC_HAS_ICACHE
129 struct cpuinfo_arc_cache *ic;
131 #ifdef CONFIG_ARC_HAS_DCACHE
132 struct cpuinfo_arc_cache *dc;
134 int way_pg_ratio = way_pg_ratio;
136 #ifdef CONFIG_ARC_HAS_ICACHE
137 ic = &cpuinfo_arc700[cpu].icache;
140 * if Cache way size is <= page size then no aliasing exhibited
141 * otherwise ratio determines num of aliases.
142 * e.g. 32K I$, 2 way set assoc, 8k pg size
143 * way-sz = 32k/2 = 16k
144 * way-pg-ratio = 16k/8k = 2, so 2 aliases possible
145 * (meaning 1 line could be in 2 possible locations).
147 way_pg_ratio = ic->sz / ARC_ICACHE_WAYS / PAGE_SIZE;
148 switch (way_pg_ratio) {
151 ___flush_icache_rtn = __ic_line_inv_no_alias;
154 ___flush_icache_rtn = __ic_line_inv_2_alias;
157 ___flush_icache_rtn = __ic_line_inv_4_alias;
160 panic("Unsupported I-Cache Sz\n");
164 /* Enable/disable I-Cache */
165 temp = read_aux_reg(ARC_REG_IC_CTRL);
167 #ifdef CONFIG_ARC_HAS_ICACHE
168 temp &= ~IC_CTRL_CACHE_DISABLE;
170 temp |= IC_CTRL_CACHE_DISABLE;
173 write_aux_reg(ARC_REG_IC_CTRL, temp);
175 #ifdef CONFIG_ARC_HAS_DCACHE
176 dc = &cpuinfo_arc700[cpu].dcache;
178 /* check for D-Cache aliasing */
179 if ((dc->sz / ARC_DCACHE_WAYS) > PAGE_SIZE)
180 panic("D$ aliasing not handled right now\n");
183 /* Set the default Invalidate Mode to "simpy discard dirty lines"
184 * as this is more frequent then flush before invalidate
185 * Ofcourse we toggle this default behviour when desired
187 temp = read_aux_reg(ARC_REG_DC_CTRL);
188 temp &= ~DC_CTRL_INV_MODE_FLUSH;
190 #ifdef CONFIG_ARC_HAS_DCACHE
191 /* Enable D-Cache: Clear Bit 0 */
192 write_aux_reg(ARC_REG_DC_CTRL, temp & ~IC_CTRL_CACHE_DISABLE);
195 write_aux_reg(ARC_REG_DC_FLSH, 0x1);
196 /* Disable D cache */
197 write_aux_reg(ARC_REG_DC_CTRL, temp | IC_CTRL_CACHE_DISABLE);
205 #define OP_FLUSH_N_INV 0x3
207 #ifdef CONFIG_ARC_HAS_DCACHE
209 /***************************************************************
210 * Machine specific helpers for Entire D-Cache or Per Line ops
213 static inline void wait_for_flush(void)
215 while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
220 * Operation on Entire D-Cache
221 * @cacheop = {OP_INV, OP_FLUSH, OP_FLUSH_N_INV}
222 * Note that constant propagation ensures all the checks are gone
225 static inline void __dc_entire_op(const int cacheop)
227 unsigned long flags, tmp = tmp;
230 local_irq_save(flags);
232 if (cacheop == OP_FLUSH_N_INV) {
233 /* Dcache provides 2 cmd: FLUSH or INV
234 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
235 * flush-n-inv is achieved by INV cmd but with IM=1
236 * Default INV sub-mode is DISCARD, which needs to be toggled
238 tmp = read_aux_reg(ARC_REG_DC_CTRL);
239 write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
242 if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */
243 aux = ARC_REG_DC_IVDC;
245 aux = ARC_REG_DC_FLSH;
247 write_aux_reg(aux, 0x1);
249 if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */
252 /* Switch back the DISCARD ONLY Invalidate mode */
253 if (cacheop == OP_FLUSH_N_INV)
254 write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
256 local_irq_restore(flags);
260 * Per Line Operation on D-Cache
261 * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete
262 * It's sole purpose is to help gcc generate ZOL
264 static inline void __dc_line_loop(unsigned long start, unsigned long sz,
267 int num_lines, slack;
269 /* Ensure we properly floor/ceil the non-line aligned/sized requests
270 * and have @start - aligned to cache line and integral @num_lines.
271 * This however can be avoided for page sized since:
272 * -@start will be cache-line aligned already (being page aligned)
273 * -@sz will be integral multiple of line size (being page sized).
275 if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
276 slack = start & ~DCACHE_LINE_MASK;
281 num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN);
283 while (num_lines-- > 0) {
284 #if (CONFIG_ARC_MMU_VER > 2)
286 * Just as for I$, in MMU v3, D$ ops also require
287 * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops
288 * But we pass phy addr for both. This works since Linux
289 * doesn't support aliasing configs for D$, yet.
290 * Thus paddr is enough to provide both tag and index.
292 write_aux_reg(ARC_REG_DC_PTAG, start);
294 write_aux_reg(aux_reg, start);
295 start += ARC_DCACHE_LINE_LEN;
300 * D-Cache : Per Line INV (discard or wback+discard) or FLUSH (wback)
302 static inline void __dc_line_op(unsigned long start, unsigned long sz,
305 unsigned long flags, tmp = tmp;
308 local_irq_save(flags);
310 if (cacheop == OP_FLUSH_N_INV) {
312 * Dcache provides 2 cmd: FLUSH or INV
313 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
314 * flush-n-inv is achieved by INV cmd but with IM=1
315 * Default INV sub-mode is DISCARD, which needs to be toggled
317 tmp = read_aux_reg(ARC_REG_DC_CTRL);
318 write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
321 if (cacheop & OP_INV) /* Inv / flush-n-inv use same cmd reg */
322 aux = ARC_REG_DC_IVDL;
324 aux = ARC_REG_DC_FLDL;
326 __dc_line_loop(start, sz, aux);
328 if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */
331 /* Switch back the DISCARD ONLY Invalidate mode */
332 if (cacheop == OP_FLUSH_N_INV)
333 write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
335 local_irq_restore(flags);
340 #define __dc_entire_op(cacheop)
341 #define __dc_line_op(start, sz, cacheop)
343 #endif /* CONFIG_ARC_HAS_DCACHE */
346 #ifdef CONFIG_ARC_HAS_ICACHE
349 * I-Cache Aliasing in ARC700 VIPT caches
351 * For fetching code from I$, ARC700 uses vaddr (embedded in program code)
352 * to "index" into SET of cache-line and paddr from MMU to match the TAG
353 * in the WAYS of SET.
355 * However the CDU iterface (to flush/inv) lines from software, only takes
356 * paddr (to have simpler hardware interface). For simpler cases, using paddr
358 * e.g. 2-way-set-assoc, 16K I$ (8k MMU pg sz, 32b cache line size):
359 * way_sz = cache_sz / num_ways = 16k/2 = 8k
360 * num_sets = way_sz / line_sz = 8k/32 = 256 => 8 bits
361 * Ignoring the bottom 5 bits corresp to the off within a 32b cacheline,
362 * bits req for calc set-index = bits 12:5 (0 based). Since this range fits
363 * inside the bottom 13 bits of paddr, which are same for vaddr and paddr
364 * (with 8k pg sz), paddr alone can be safely used by CDU to unambigously
365 * locate a cache-line.
367 * However for a difft sized cache, say 32k I$, above math yields need
368 * for 14 bits of vaddr to locate a cache line, which can't be provided by
369 * paddr, since the bit 13 (0 based) might differ between the two.
371 * This lack of extra bits needed for correct line addressing, defines the
372 * classical problem of Cache aliasing with VIPT architectures
373 * num_aliases = 1 << extra_bits
374 * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz => 2 aliases
375 * 2-way-set-assoc, 64K I$ with 8k MMU pg sz => 4 aliases
376 * 2-way-set-assoc, 16K I$ with 8k MMU pg sz => NO aliases
379 * MMU v1/v2 (Fixed Page Size 8k)
381 * The solution was to provide CDU with these additonal vaddr bits. These
382 * would be bits [x:13], x would depend on cache-geom.
383 * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits
384 * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the
385 * orig 5 bits of paddr were anyways ignored by CDU line ops, as they
386 * represent the offset within cache-line. The adv of using this "clumsy"
387 * interface for additional info was no new reg was needed in CDU.
389 * 17:13 represented the max num of bits passable, actual bits needed were
390 * fewer, based on the num-of-aliases possible.
391 * -for 2 alias possibility, only bit 13 needed (32K cache)
392 * -for 4 alias possibility, bits 14:13 needed (64K cache)
394 * Since vaddr was not available for all instances of I$ flush req by core
395 * kernel, the only safe way (non-optimal though) was to kill all possible
396 * lines which could represent an alias (even if they didnt represent one
398 * e.g. for 64K I$, 4 aliases possible, so we did
404 * The penalty was invoking the operation itself, since tag match is anyways
405 * paddr based, a line which didn't represent an alias would not match the
406 * paddr, hence wont be killed
408 * Note that aliasing concerns are independent of line-sz for a given cache
409 * geometry (size + set_assoc) because the extra bits required by line-sz are
410 * reduced from the set calc.
411 * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz and using math above
412 * 32b line-sz: 9 bits set-index-calc, 5 bits offset-in-line => 1 extra bit
413 * 64b line-sz: 8 bits set-index-calc, 6 bits offset-in-line => 1 extra bit
418 * This ver of MMU supports var page sizes (1k-16k) - Linux will support
419 * 8k (default), 16k and 4k.
420 * However from hardware perspective, smaller page sizes aggrevate aliasing
421 * meaning more vaddr bits needed to disambiguate the cache-line-op ;
422 * the existing scheme of piggybacking won't work for certain configurations.
423 * Two new registers IC_PTAG and DC_PTAG inttoduced.
424 * "tag" bits are provided in PTAG, index bits in existing IVIL/IVDL/FLDL regs
427 /***********************************************************
428 * Machine specific helpers for per line I-Cache invalidate.
429 * 3 routines to accpunt for 1, 2, 4 aliases possible
432 static void __ic_line_inv_no_alias(unsigned long start, int num_lines)
434 while (num_lines-- > 0) {
435 #if (CONFIG_ARC_MMU_VER > 2)
436 write_aux_reg(ARC_REG_IC_PTAG, start);
438 write_aux_reg(ARC_REG_IC_IVIL, start);
439 start += ARC_ICACHE_LINE_LEN;
443 static void __ic_line_inv_2_alias(unsigned long start, int num_lines)
445 while (num_lines-- > 0) {
447 #if (CONFIG_ARC_MMU_VER > 2)
449 * MMU v3, CDU prog model (for line ops) now uses a new IC_PTAG
450 * reg to pass the "tag" bits and existing IVIL reg only looks
451 * at bits relevant for "index" (details above)
453 * -when writing tag to PTAG reg, bit chopping can be avoided,
454 * CDU ignores non-tag bits.
455 * -Ideally "index" must be computed from vaddr, but it is not
456 * avail in these rtns. So to be safe, we kill the lines in all
457 * possible indexes corresp to num of aliases possible for
458 * given cache config.
460 write_aux_reg(ARC_REG_IC_PTAG, start);
461 write_aux_reg(ARC_REG_IC_IVIL,
462 start & ~(0x1 << PAGE_SHIFT));
463 write_aux_reg(ARC_REG_IC_IVIL, start | (0x1 << PAGE_SHIFT));
465 write_aux_reg(ARC_REG_IC_IVIL, start);
466 write_aux_reg(ARC_REG_IC_IVIL, start | 0x01);
468 start += ARC_ICACHE_LINE_LEN;
472 static void __ic_line_inv_4_alias(unsigned long start, int num_lines)
474 while (num_lines-- > 0) {
476 #if (CONFIG_ARC_MMU_VER > 2)
477 write_aux_reg(ARC_REG_IC_PTAG, start);
479 write_aux_reg(ARC_REG_IC_IVIL,
480 start & ~(0x3 << PAGE_SHIFT));
481 write_aux_reg(ARC_REG_IC_IVIL,
482 start & ~(0x2 << PAGE_SHIFT));
483 write_aux_reg(ARC_REG_IC_IVIL,
484 start & ~(0x1 << PAGE_SHIFT));
485 write_aux_reg(ARC_REG_IC_IVIL, start | (0x3 << PAGE_SHIFT));
487 write_aux_reg(ARC_REG_IC_IVIL, start);
488 write_aux_reg(ARC_REG_IC_IVIL, start | 0x01);
489 write_aux_reg(ARC_REG_IC_IVIL, start | 0x02);
490 write_aux_reg(ARC_REG_IC_IVIL, start | 0x03);
492 start += ARC_ICACHE_LINE_LEN;
496 static void __ic_line_inv(unsigned long start, unsigned long sz)
499 int num_lines, slack;
502 * Ensure we properly floor/ceil the non-line aligned/sized requests
503 * and have @start - aligned to cache line, and integral @num_lines
504 * However page sized flushes can be compile time optimised.
505 * -@start will be cache-line aligned already (being page aligned)
506 * -@sz will be integral multiple of line size (being page sized).
508 if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
509 slack = start & ~ICACHE_LINE_MASK;
514 num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
516 local_irq_save(flags);
517 (*___flush_icache_rtn) (start, num_lines);
518 local_irq_restore(flags);
521 /* Unlike routines above, having vaddr for flush op (along with paddr),
522 * prevents the need to speculatively kill the lines in multiple sets
523 * based on ratio of way_sz : pg_sz
525 static void __ic_line_inv_vaddr(unsigned long phy_start,
526 unsigned long vaddr, unsigned long sz)
529 int num_lines, slack;
532 slack = phy_start & ~ICACHE_LINE_MASK;
535 num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
537 #if (CONFIG_ARC_MMU_VER > 2)
538 vaddr &= ~ICACHE_LINE_MASK;
541 /* bits 17:13 of vaddr go as bits 4:0 of paddr */
542 addr = phy_start | ((vaddr >> 13) & 0x1F);
545 local_irq_save(flags);
546 while (num_lines-- > 0) {
547 #if (CONFIG_ARC_MMU_VER > 2)
548 /* tag comes from phy addr */
549 write_aux_reg(ARC_REG_IC_PTAG, addr);
551 /* index bits come from vaddr */
552 write_aux_reg(ARC_REG_IC_IVIL, vaddr);
553 vaddr += ARC_ICACHE_LINE_LEN;
555 /* this paddr contains vaddrs bits as needed */
556 write_aux_reg(ARC_REG_IC_IVIL, addr);
558 addr += ARC_ICACHE_LINE_LEN;
560 local_irq_restore(flags);
565 #define __ic_line_inv(start, sz)
566 #define __ic_line_inv_vaddr(pstart, vstart, sz)
568 #endif /* CONFIG_ARC_HAS_ICACHE */
571 /***********************************************************
575 /* TBD: use pg_arch_1 to optimize this */
576 void flush_dcache_page(struct page *page)
578 __dc_line_op((unsigned long)page_address(page), PAGE_SIZE, OP_FLUSH);
580 EXPORT_SYMBOL(flush_dcache_page);
583 void dma_cache_wback_inv(unsigned long start, unsigned long sz)
585 __dc_line_op(start, sz, OP_FLUSH_N_INV);
587 EXPORT_SYMBOL(dma_cache_wback_inv);
589 void dma_cache_inv(unsigned long start, unsigned long sz)
591 __dc_line_op(start, sz, OP_INV);
593 EXPORT_SYMBOL(dma_cache_inv);
595 void dma_cache_wback(unsigned long start, unsigned long sz)
597 __dc_line_op(start, sz, OP_FLUSH);
599 EXPORT_SYMBOL(dma_cache_wback);
602 * This is API for making I/D Caches consistent when modifying code
603 * (loadable modules, kprobes, etc)
604 * This is called on insmod, with kernel virtual address for CODE of
605 * the module. ARC cache maintenance ops require PHY address thus we
606 * need to convert vmalloc addr to PHY addr
608 void flush_icache_range(unsigned long kstart, unsigned long kend)
610 unsigned int tot_sz, off, sz;
611 unsigned long phy, pfn;
614 /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
616 /* This is not the right API for user virtual address */
617 if (kstart < TASK_SIZE) {
618 BUG_ON("Flush icache range for user virtual addr space");
622 /* Shortcut for bigger flush ranges.
623 * Here we don't care if this was kernel virtual or phy addr
625 tot_sz = kend - kstart;
626 if (tot_sz > PAGE_SIZE) {
631 /* Case: Kernel Phy addr (0x8000_0000 onwards) */
632 if (likely(kstart > PAGE_OFFSET)) {
633 __ic_line_inv(kstart, kend - kstart);
634 __dc_line_op(kstart, kend - kstart, OP_FLUSH);
639 * Case: Kernel Vaddr (0x7000_0000 to 0x7fff_ffff)
640 * (1) ARC Cache Maintenance ops only take Phy addr, hence special
641 * handling of kernel vaddr.
643 * (2) Despite @tot_sz being < PAGE_SIZE (bigger cases handled already),
644 * it still needs to handle a 2 page scenario, where the range
645 * straddles across 2 virtual pages and hence need for loop
648 off = kstart % PAGE_SIZE;
649 pfn = vmalloc_to_pfn((void *)kstart);
650 phy = (pfn << PAGE_SHIFT) + off;
651 sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off);
652 local_irq_save(flags);
653 __dc_line_op(phy, sz, OP_FLUSH);
654 __ic_line_inv(phy, sz);
655 local_irq_restore(flags);
662 * Optimised ver of flush_icache_range() with spec callers: ptrace/signals
663 * where vaddr is also available. This allows passing both vaddr and paddr
664 * bits to CDU for cache flush, short-circuting the current pessimistic algo
665 * which kills all possible aliases.
666 * An added adv of knowing that vaddr is user-vaddr avoids various checks
667 * and handling for k-vaddr, k-paddr as done in orig ver above
669 void flush_icache_range_vaddr(unsigned long paddr, unsigned long u_vaddr,
672 __ic_line_inv_vaddr(paddr, u_vaddr, len);
673 __dc_line_op(paddr, len, OP_FLUSH);
677 * XXX: This also needs to be optim using pg_arch_1
678 * This is called when a page-cache page is about to be mapped into a
679 * user process' address space. It offers an opportunity for a
680 * port to ensure d-cache/i-cache coherency if necessary.
682 void flush_icache_page(struct vm_area_struct *vma, struct page *page)
684 if (!(vma->vm_flags & VM_EXEC))
687 __ic_line_inv((unsigned long)page_address(page), PAGE_SIZE);
690 void flush_icache_all(void)
694 local_irq_save(flags);
696 write_aux_reg(ARC_REG_IC_IVIC, 1);
698 /* lr will not complete till the icache inv operation is not over */
699 read_aux_reg(ARC_REG_IC_CTRL);
700 local_irq_restore(flags);
703 noinline void flush_cache_all(void)
707 local_irq_save(flags);
710 __dc_entire_op(OP_FLUSH_N_INV);
712 local_irq_restore(flags);
716 /**********************************************************************
717 * Explicit Cache flush request from user space via syscall
718 * Needed for JITs which generate code on the fly
720 SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
722 /* TBD: optimize this */