Rev 3022 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3022 | Rev 4055 | ||
---|---|---|---|
Line 46... | Line 46... | ||
46 | #include <genarch/mm/page_ht.h> |
46 | #include <genarch/mm/page_ht.h> |
47 | #include <align.h> |
47 | #include <align.h> |
48 | #include <memstr.h> |
48 | #include <memstr.h> |
49 | #include <macros.h> |
49 | #include <macros.h> |
50 | #include <arch.h> |
50 | #include <arch.h> |
- | 51 | #include <arch/barrier.h> |
|
51 | 52 | ||
52 | #ifdef CONFIG_VIRT_IDX_DCACHE |
53 | #ifdef CONFIG_VIRT_IDX_DCACHE |
53 | #include <arch/mm/cache.h> |
54 | #include <arch/mm/cache.h> |
54 | #endif |
55 | #endif |
55 | 56 | ||
Line 65... | Line 66... | ||
65 | 66 | ||
66 | /** Service a page fault in the ELF backend address space area. |
67 | /** Service a page fault in the ELF backend address space area. |
67 | * |
68 | * |
68 | * The address space area and page tables must be already locked. |
69 | * The address space area and page tables must be already locked. |
69 | * |
70 | * |
70 | * @param area Pointer to the address space area. |
71 | * @param area Pointer to the address space area. |
71 | * @param addr Faulting virtual address. |
72 | * @param addr Faulting virtual address. |
72 | * @param access Access mode that caused the fault (i.e. read/write/exec). |
73 | * @param access Access mode that caused the fault (i.e. |
- | 74 | * read/write/exec). |
|
73 | * |
75 | * |
74 | * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. |
76 | * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK |
75 | * serviced). |
77 | * on success (i.e. serviced). |
76 | */ |
78 | */ |
77 | int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
79 | int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
78 | { |
80 | { |
79 | elf_header_t *elf = area->backend_data.elf; |
81 | elf_header_t *elf = area->backend_data.elf; |
80 | elf_segment_header_t *entry = area->backend_data.segment; |
82 | elf_segment_header_t *entry = area->backend_data.segment; |
Line 114... | Line 116... | ||
114 | /* |
116 | /* |
115 | * Workaround for valid NULL address. |
117 | * Workaround for valid NULL address. |
116 | */ |
118 | */ |
117 | 119 | ||
118 | for (i = 0; i < leaf->keys; i++) { |
120 | for (i = 0; i < leaf->keys; i++) { |
119 | if (leaf->key[i] == page) { |
121 | if (leaf->key[i] == page - area->base) { |
120 | found = true; |
122 | found = true; |
121 | break; |
123 | break; |
122 | } |
124 | } |
123 | } |
125 | } |
124 | } |
126 | } |
125 | if (frame || found) { |
127 | if (frame || found) { |
126 | frame_reference_add(ADDR2PFN(frame)); |
128 | frame_reference_add(ADDR2PFN(frame)); |
127 | page_mapping_insert(AS, addr, frame, |
129 | page_mapping_insert(AS, addr, frame, |
128 | as_area_get_flags(area)); |
130 | as_area_get_flags(area)); |
129 | if (!used_space_insert(area, page, 1)) |
131 | if (!used_space_insert(area, page, 1)) |
130 | panic("Could not insert used space.\n"); |
132 | panic("Cannot insert used space."); |
131 | mutex_unlock(&area->sh_info->lock); |
133 | mutex_unlock(&area->sh_info->lock); |
132 | return AS_PF_OK; |
134 | return AS_PF_OK; |
133 | } |
135 | } |
134 | } |
136 | } |
135 | 137 | ||
Line 148... | Line 150... | ||
148 | */ |
150 | */ |
149 | if (entry->p_flags & PF_W) { |
151 | if (entry->p_flags & PF_W) { |
150 | frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
152 | frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
151 | memcpy((void *) PA2KA(frame), |
153 | memcpy((void *) PA2KA(frame), |
152 | (void *) (base + i * FRAME_SIZE), FRAME_SIZE); |
154 | (void *) (base + i * FRAME_SIZE), FRAME_SIZE); |
- | 155 | if (entry->p_flags & PF_X) { |
|
- | 156 | smc_coherence_block((void *) PA2KA(frame), |
|
- | 157 | FRAME_SIZE); |
|
- | 158 | } |
|
153 | dirty = true; |
159 | dirty = true; |
154 | } else { |
160 | } else { |
155 | frame = KA2PA(base + i * FRAME_SIZE); |
161 | frame = KA2PA(base + i * FRAME_SIZE); |
156 | } |
162 | } |
157 | } else if (page >= start_anon) { |
163 | } else if (page >= start_anon) { |
Line 160... | Line 166... | ||
160 | * It is not physically present in the ELF image. |
166 | * It is not physically present in the ELF image. |
161 | * To resolve the situation, a frame must be allocated |
167 | * To resolve the situation, a frame must be allocated |
162 | * and cleared. |
168 | * and cleared. |
163 | */ |
169 | */ |
164 | frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
170 | frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
165 | memsetb(PA2KA(frame), FRAME_SIZE, 0); |
171 | memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
166 | dirty = true; |
172 | dirty = true; |
167 | } else { |
173 | } else { |
168 | size_t pad_lo, pad_hi; |
174 | size_t pad_lo, pad_hi; |
169 | /* |
175 | /* |
170 | * The mixed case. |
176 | * The mixed case. |
Line 185... | Line 191... | ||
185 | 191 | ||
186 | frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
192 | frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
187 | memcpy((void *) (PA2KA(frame) + pad_lo), |
193 | memcpy((void *) (PA2KA(frame) + pad_lo), |
188 | (void *) (base + i * FRAME_SIZE + pad_lo), |
194 | (void *) (base + i * FRAME_SIZE + pad_lo), |
189 | FRAME_SIZE - pad_lo - pad_hi); |
195 | FRAME_SIZE - pad_lo - pad_hi); |
- | 196 | if (entry->p_flags & PF_X) { |
|
- | 197 | smc_coherence_block((void *) (PA2KA(frame) + pad_lo), |
|
- | 198 | FRAME_SIZE - pad_lo - pad_hi); |
|
- | 199 | } |
|
190 | memsetb(PA2KA(frame), pad_lo, 0); |
200 | memsetb((void *) PA2KA(frame), pad_lo, 0); |
191 | memsetb(PA2KA(frame) + FRAME_SIZE - pad_hi, pad_hi, 0); |
201 | memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi, |
- | 202 | 0); |
|
192 | dirty = true; |
203 | dirty = true; |
193 | } |
204 | } |
194 | 205 | ||
195 | if (dirty && area->sh_info) { |
206 | if (dirty && area->sh_info) { |
196 | frame_reference_add(ADDR2PFN(frame)); |
207 | frame_reference_add(ADDR2PFN(frame)); |
Line 201... | Line 212... | ||
201 | if (area->sh_info) |
212 | if (area->sh_info) |
202 | mutex_unlock(&area->sh_info->lock); |
213 | mutex_unlock(&area->sh_info->lock); |
203 | 214 | ||
204 | page_mapping_insert(AS, addr, frame, as_area_get_flags(area)); |
215 | page_mapping_insert(AS, addr, frame, as_area_get_flags(area)); |
205 | if (!used_space_insert(area, page, 1)) |
216 | if (!used_space_insert(area, page, 1)) |
206 | panic("Could not insert used space.\n"); |
217 | panic("Cannot insert used space."); |
207 | 218 | ||
208 | return AS_PF_OK; |
219 | return AS_PF_OK; |
209 | } |
220 | } |
210 | 221 | ||
211 | /** Free a frame that is backed by the ELF backend. |
222 | /** Free a frame that is backed by the ELF backend. |
212 | * |
223 | * |
213 | * The address space area and page tables must be already locked. |
224 | * The address space area and page tables must be already locked. |
214 | * |
225 | * |
215 | * @param area Pointer to the address space area. |
226 | * @param area Pointer to the address space area. |
216 | * @param page Page that is mapped to frame. Must be aligned to PAGE_SIZE. |
227 | * @param page Page that is mapped to frame. Must be aligned to |
- | 228 | * PAGE_SIZE. |
|
217 | * @param frame Frame to be released. |
229 | * @param frame Frame to be released. |
218 | * |
230 | * |
219 | */ |
231 | */ |
220 | void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame) |
232 | void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame) |
221 | { |
233 | { |
222 | elf_header_t *elf = area->backend_data.elf; |
234 | elf_header_t *elf = area->backend_data.elf; |
Line 255... | Line 267... | ||
255 | * Otherwise only portions of the area that are not backed by the ELF image |
267 | * Otherwise only portions of the area that are not backed by the ELF image |
256 | * are put into the pagemap. |
268 | * are put into the pagemap. |
257 | * |
269 | * |
258 | * The address space and address space area must be locked prior to the call. |
270 | * The address space and address space area must be locked prior to the call. |
259 | * |
271 | * |
260 | * @param area Address space area. |
272 | * @param area Address space area. |
261 | */ |
273 | */ |
262 | void elf_share(as_area_t *area) |
274 | void elf_share(as_area_t *area) |
263 | { |
275 | { |
264 | elf_segment_header_t *entry = area->backend_data.segment; |
276 | elf_segment_header_t *entry = area->backend_data.segment; |
265 | link_t *cur; |
277 | link_t *cur; |