]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/mem_op.cpp
update
[l4.git] / kernel / fiasco / src / kern / arm / mem_op.cpp
1 INTERFACE [arm]:
2
3 #include "types.h"
4
5 class Mem_op
6 {
7 public:
8   enum Op_cache
9   {
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   };
17
18   enum Op_mem
19   {
20     Op_mem_read_data     = 0x10,
21     Op_mem_write_data    = 0x11,
22   };
23 };
24
25 // ------------------------------------------------------------------------
26 IMPLEMENTATION [arm]:
27
28 #include "context.h"
29 #include "entry_frame.h"
30 #include "globals.h"
31 #include "mem.h"
32 #include "mem_space.h"
33 #include "mem_unit.h"
34 #include "outer_cache.h"
35 #include "space.h"
36 #include "warn.h"
37
38 PUBLIC static void
39 Mem_op::arm_mem_cache_maint(int op, void const *start, void const *end)
40 {
41   Context *c = current();
42
43   c->set_ignore_mem_op_in_progress(true);
44
45   switch (op)
46     {
47     case Op_cache_clean_data:
48       Mem_unit::clean_dcache(start, end);
49       break;
50
51     case Op_cache_flush_data:
52       Mem_unit::flush_dcache(start, end);
53       break;
54
55     case Op_cache_inv_data:
56       Mem_unit::inv_dcache(start, end);
57       break;
58
59     case Op_cache_coherent:
60       Mem_unit::clean_dcache(start, end);
61       Mem::dsb();
62       Mem_unit::btc_inv();
63       break;
64
65     case Op_cache_dma_coherent:
66         {
67           Mem_space::Vaddr v = Virt_addr(Address(start));
68           Mem_space::Vaddr e = Virt_addr(Address(end));
69
70           Mem_unit::flush_dcache(v, e);
71           while (v < e)
72             {
73               Mem_space::Size phys_size;
74               Mem_space::Phys_addr phys_addr;
75               unsigned attrs;
76
77               if (   c->mem_space()->v_lookup(v, &phys_addr,
78                                               &phys_size, &attrs)
79                   && (attrs & Mem_space::Page_user_accessible))
80                 {
81                   Outer_cache::flush(Virt_addr(phys_addr).value(),
82                                      Virt_addr(phys_addr).value()
83                                      + Virt_size(phys_size).value() - 1,
84                                      false);
85                 }
86               v += phys_size;
87             }
88           Outer_cache::sync();
89
90         }
91       break;
92
93     // We might not want to implement this one but single address outer
94     // cache flushing can be really slow
95     case Op_cache_dma_coherent_full:
96       Mem_unit::flush_dcache();
97       Outer_cache::flush();
98       break;
99
100     default:
101       break;
102     };
103
104   c->set_ignore_mem_op_in_progress(false);
105 }
106
107 PUBLIC static void
108 Mem_op::arm_mem_access(Mword *r)
109 {
110   Address  a = r[1];
111   unsigned w = r[2];
112
113   if (w > 2)
114     return;
115
116   if (!current()->space()->is_user_memory(a, 1 << w))
117     return;
118
119   jmp_buf pf_recovery;
120   int e;
121
122   if ((e = setjmp(pf_recovery)) == 0)
123     {
124       current()->recover_jmp_buf(&pf_recovery);
125
126       switch (r[0])
127         {
128         case Op_mem_read_data:
129           switch (w)
130             {
131             case 0:
132               r[3] = *(unsigned char *)a;
133               break;
134             case 1:
135               r[3] = *(unsigned short *)a;
136               break;
137             case 2:
138               r[3] = *(unsigned int *)a;
139               break;
140             default:
141               break;
142             };
143           break;
144
145         case Op_mem_write_data:
146           switch (w)
147             {
148             case 0:
149               *(unsigned char *)a = r[3];
150               break;
151             case 1:
152               *(unsigned short *)a = r[3];
153               break;
154             case 2:
155               *(unsigned int *)a = r[3];
156               break;
157             default:
158               break;
159             };
160           break;
161
162         default:
163           break;
164         };
165     }
166   else
167     WARN("Unresolved memory access, skipping\n");
168
169   current()->recover_jmp_buf(0);
170 }
171
172 extern "C" void sys_arm_mem_op()
173 {
174   Entry_frame *e = current()->regs();
175   if (EXPECT_FALSE(e->r[0] & 0x10))
176     Mem_op::arm_mem_access(e->r);
177   else
178     Mem_op::arm_mem_cache_maint(e->r[0], (void *)e->r[1], (void *)e->r[2]);
179 }