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;
57 Mem_unit::inv_dcache((void *)start, (void *)end);
61 Mem_op::inv_icache(Address start, Address end)
63 if (Address(end) - Address(start) > 0x2000)
64 asm volatile("mcr p15, 0, r0, c7, c5, 0");
67 for (start &= ~Mem_unit::Icache_line_mask;
68 start < end; start += Mem_unit::Icache_line_size)
69 asm volatile("mcr p15, 0, %0, c7, c5, 1" : : "r" (start));
74 Mem_op::arm_mem_cache_maint(int op, void const *start, void const *end)
76 Context *c = current();
78 if (EXPECT_FALSE(start > end))
81 c->set_ignore_mem_op_in_progress(true);
85 case Op_cache_clean_data:
86 Mem_unit::clean_dcache(start, end);
89 case Op_cache_flush_data:
90 Mem_unit::flush_dcache(start, end);
93 case Op_cache_inv_data:
94 l1_inv_dcache((Address)start, (Address)end);
97 case Op_cache_coherent:
98 Mem_unit::clean_dcache(start, end);
101 inv_icache(Address(start), Address(end));
105 case Op_cache_l2_clean:
106 case Op_cache_l2_flush:
107 case Op_cache_l2_inv:
108 outer_cache_op(op, Address(start), Address(end));
111 case Op_cache_dma_coherent:
113 Mem_unit::flush_dcache(Virt_addr(Address(start)), Virt_addr(Address(end)));
114 outer_cache_op(Op_cache_l2_flush, Address(start), Address(end));
118 // We might not want to implement this one but single address outer
119 // cache flushing can be really slow
120 case Op_cache_dma_coherent_full:
121 Mem_unit::flush_dcache();
122 Outer_cache::flush();
129 c->set_ignore_mem_op_in_progress(false);
133 Mem_op::arm_mem_access(Mword *r)
141 if (!current()->space()->is_user_memory(a, 1 << w))
147 if ((e = setjmp(pf_recovery)) == 0)
149 current()->recover_jmp_buf(&pf_recovery);
153 case Op_mem_read_data:
157 r[3] = *(unsigned char *)a;
160 r[3] = *(unsigned short *)a;
163 r[3] = *(unsigned int *)a;
170 case Op_mem_write_data:
174 *(unsigned char *)a = r[3];
177 *(unsigned short *)a = r[3];
180 *(unsigned int *)a = r[3];
192 WARN("Unresolved memory access, skipping\n");
194 current()->recover_jmp_buf(0);
197 extern "C" void sys_arm_mem_op()
199 Entry_frame *e = current()->regs();
200 if (EXPECT_FALSE(e->r[0] & 0x10))
201 Mem_op::arm_mem_access(e->r);
203 Mem_op::arm_mem_cache_maint(e->r[0], (void *)e->r[1], (void *)e->r[2]);
206 // ------------------------------------------------------------------------
207 IMPLEMENTATION [arm && !outer_cache]:
209 PRIVATE static inline
211 Mem_op::outer_cache_op(int, Address, Address)
214 // ------------------------------------------------------------------------
215 IMPLEMENTATION [arm && outer_cache]:
219 Mem_op::outer_cache_op(int op, Address start, Address end)
222 Virt_addr s = Virt_addr(start);
223 Virt_addr v = Virt_addr(start);
224 Virt_addr e = Virt_addr(end);
226 Context *c = current();
230 Mem_space::Size phys_size;
231 Mem_space::Phys_addr phys_addr;
233 bool mapped = c->mem_space()->v_lookup(Mem_space::Vaddr(v), &phys_addr, &phys_size, &attrs)
234 && (attrs & Mem_space::Page_user_accessible);
236 Virt_size sz = Virt_size(phys_size);
237 Virt_size offs = Virt_size(Virt_addr(v).value() & (Mem_space::Size(phys_size).value() - 1));
244 Virt_addr vstart = Virt_addr(phys_addr) | offs;
245 Virt_addr vend = vstart + sz;
248 case Op_cache_l2_clean:
249 Outer_cache::clean(Virt_addr(vstart).value(),
250 Virt_addr(vend).value(), false);
252 case Op_cache_l2_flush:
253 Outer_cache::flush(Virt_addr(vstart).value(),
254 Virt_addr(vend).value(), false);
256 case Op_cache_l2_inv:
257 Outer_cache::invalidate(Virt_addr(vstart).value(),
258 Virt_addr(vend).value(), false);