10 Op_cache_clean_data = 0x00,
11 Op_cache_flush_data = 0x01,
12 Op_cache_inv_data = 0x02,
13 Op_cache_coherent = 0x03,
14 Op_cache_dma_coherent = 0x04,
15 Op_cache_dma_coherent_full = 0x05,
16 Op_cache_l2_clean = 0x06,
17 Op_cache_l2_flush = 0x07,
18 Op_cache_l2_inv = 0x08,
23 Op_mem_read_data = 0x10,
24 Op_mem_write_data = 0x11,
28 // ------------------------------------------------------------------------
32 #include "entry_frame.h"
35 #include "mem_space.h"
37 #include "outer_cache.h"
42 Mem_op::l1_inv_dcache(Address start, Address end)
44 if (start & Mem_unit::Cache_line_mask)
46 Mem_unit::flush_dcache((void *)start, (void *)start);
47 start += Mem_unit::Cache_line_size;
48 start &= ~Mem_unit::Cache_line_mask;
50 if (end & Mem_unit::Cache_line_mask)
52 Mem_unit::flush_dcache((void *)end, (void *)end);
53 end &= ~Mem_unit::Cache_line_mask;
56 Mem_unit::inv_dcache((void *)start, (void *)end);
60 Mem_op::inv_icache(Address start, Address end)
62 if (Address(end) - Address(start) > 0x2000)
63 asm volatile("mcr p15, 0, r0, c7, c5, 0");
66 for (start &= ~Mem_unit::Icache_line_mask;
67 start < end; start += Mem_unit::Icache_line_size)
68 asm volatile("mcr p15, 0, %0, c7, c5, 1" : : "r" (start));
73 Mem_op::arm_mem_cache_maint(int op, void const *start, void const *end)
75 Context *c = current();
77 if (EXPECT_FALSE(start > end))
80 c->set_ignore_mem_op_in_progress(true);
84 case Op_cache_clean_data:
85 Mem_unit::clean_dcache(start, end);
88 case Op_cache_flush_data:
89 Mem_unit::flush_dcache(start, end);
92 case Op_cache_inv_data:
93 l1_inv_dcache((Address)start, (Address)end);
96 case Op_cache_coherent:
97 Mem_unit::clean_dcache(start, end);
100 inv_icache(Address(start), Address(end));
104 case Op_cache_l2_clean:
105 case Op_cache_l2_flush:
106 case Op_cache_l2_inv:
107 outer_cache_op(op, Address(start), Address(end));
110 case Op_cache_dma_coherent:
112 Mem_unit::flush_dcache(Virt_addr(Address(start)), Virt_addr(Address(end)));
113 outer_cache_op(Op_cache_l2_flush, Address(start), Address(end));
117 // We might not want to implement this one but single address outer
118 // cache flushing can be really slow
119 case Op_cache_dma_coherent_full:
120 Mem_unit::flush_dcache();
121 Outer_cache::flush();
128 c->set_ignore_mem_op_in_progress(false);
132 Mem_op::arm_mem_access(Mword *r)
140 if (!current()->space()->is_user_memory(a, 1 << w))
146 if ((e = setjmp(pf_recovery)) == 0)
148 current()->recover_jmp_buf(&pf_recovery);
152 case Op_mem_read_data:
156 r[3] = *(unsigned char *)a;
159 r[3] = *(unsigned short *)a;
162 r[3] = *(unsigned int *)a;
169 case Op_mem_write_data:
173 *(unsigned char *)a = r[3];
176 *(unsigned short *)a = r[3];
179 *(unsigned int *)a = r[3];
191 WARN("Unresolved memory access, skipping\n");
193 current()->recover_jmp_buf(0);
196 extern "C" void sys_arm_mem_op()
198 Entry_frame *e = current()->regs();
199 if (EXPECT_FALSE(e->r[0] & 0x10))
200 Mem_op::arm_mem_access(e->r);
202 Mem_op::arm_mem_cache_maint(e->r[0], (void *)e->r[1], (void *)e->r[2]);
205 // ------------------------------------------------------------------------
206 IMPLEMENTATION [arm && !outer_cache]:
208 PRIVATE static inline
210 Mem_op::outer_cache_op(int, Address, Address)
213 // ------------------------------------------------------------------------
214 IMPLEMENTATION [arm && outer_cache]:
218 Mem_op::outer_cache_op(int op, Address start, Address end)
220 Mem_space::Vaddr v = Virt_addr(Address(start));
221 Mem_space::Vaddr e = Virt_addr(Address(end));
223 Context *c = current();
227 Mem_space::Size phys_size;
228 Mem_space::Phys_addr phys_addr;
231 if ( c->mem_space()->v_lookup(v, &phys_addr, &phys_size, &attrs)
232 && (attrs & Mem_space::Page_user_accessible))
234 unsigned long sz = Virt_size(phys_size).value();
235 if (Address(end) - Address(start) < sz)
236 sz = Address(end) - Address(start);
239 case Op_cache_l2_clean:
240 Outer_cache::clean(Virt_addr(phys_addr).value(),
241 Virt_addr(phys_addr).value() + sz, false);
243 case Op_cache_l2_flush:
244 Outer_cache::flush(Virt_addr(phys_addr).value(),
245 Virt_addr(phys_addr).value() + sz, false);
247 case Op_cache_l2_inv:
248 Outer_cache::invalidate(Virt_addr(phys_addr).value(),
249 Virt_addr(phys_addr).value() + sz, false);