Rev 2009 | Rev 2071 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2009 | Rev 2015 | ||
---|---|---|---|
Line 164... | Line 164... | ||
164 | 164 | ||
165 | as->refcount = 0; |
165 | as->refcount = 0; |
166 | as->cpu_refcount = 0; |
166 | as->cpu_refcount = 0; |
167 | as->page_table = page_table_create(flags); |
167 | as->page_table = page_table_create(flags); |
168 | 168 | ||
169 | #ifdef CONFIG_VIRT_IDX_DCACHE |
- | |
170 | as->dcache_flush_on_install = false; |
- | |
171 | as->dcache_flush_on_deinstall = false; |
- | |
172 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
- | |
173 | - | ||
174 | return as; |
169 | return as; |
175 | } |
170 | } |
176 | 171 | ||
177 | /** Destroy adress space. |
172 | /** Destroy adress space. |
178 | * |
173 | * |
Line 276... | Line 271... | ||
276 | if (backend_data) |
271 | if (backend_data) |
277 | a->backend_data = *backend_data; |
272 | a->backend_data = *backend_data; |
278 | else |
273 | else |
279 | memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data), 0); |
274 | memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data), 0); |
280 | 275 | ||
281 | #ifdef CONFIG_VIRT_IDX_DCACHE |
- | |
282 | /* |
- | |
283 | * When the area is being created with the AS_AREA_ATTR_PARTIAL flag, the |
- | |
284 | * orig_color is probably wrong until the flag is reset. In other words, it is |
- | |
285 | * initialized with the color of the area being created and not with the color |
- | |
286 | * of the original address space area at the beginning of the share chain. Of |
- | |
287 | * course, the correct color is set by as_area_share() before the flag is |
- | |
288 | * reset. |
- | |
289 | */ |
- | |
290 | a->orig_color = PAGE_COLOR(base); |
- | |
291 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
- | |
292 | - | ||
293 | btree_create(&a->used_space); |
276 | btree_create(&a->used_space); |
294 | 277 | ||
295 | btree_insert(&as->as_area_btree, base, (void *) a, NULL); |
278 | btree_insert(&as->as_area_btree, base, (void *) a, NULL); |
296 | 279 | ||
297 | mutex_unlock(&as->lock); |
280 | mutex_unlock(&as->lock); |
Line 573... | Line 556... | ||
573 | * |
556 | * |
574 | * @return Zero on success or ENOENT if there is no such task or if there is no |
557 | * @return Zero on success or ENOENT if there is no such task or if there is no |
575 | * such address space area, EPERM if there was a problem in accepting the area |
558 | * such address space area, EPERM if there was a problem in accepting the area |
576 | * or ENOMEM if there was a problem in allocating destination address space |
559 | * or ENOMEM if there was a problem in allocating destination address space |
577 | * area. ENOTSUP is returned if the address space area backend does not support |
560 | * area. ENOTSUP is returned if the address space area backend does not support |
- | 561 | * sharing or if the kernel detects an attempt to create an illegal address |
|
578 | * sharing. |
562 | * alias. |
579 | */ |
563 | */ |
580 | int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
564 | int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
581 | as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
565 | as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
582 | { |
566 | { |
583 | ipl_t ipl; |
567 | ipl_t ipl; |
584 | int src_flags; |
568 | int src_flags; |
585 | size_t src_size; |
569 | size_t src_size; |
586 | int src_orig_color; |
- | |
587 | as_area_t *src_area, *dst_area; |
570 | as_area_t *src_area, *dst_area; |
588 | share_info_t *sh_info; |
571 | share_info_t *sh_info; |
589 | mem_backend_t *src_backend; |
572 | mem_backend_t *src_backend; |
590 | mem_backend_data_t src_backend_data; |
573 | mem_backend_data_t src_backend_data; |
591 | 574 | ||
Line 598... | Line 581... | ||
598 | */ |
581 | */ |
599 | mutex_unlock(&src_as->lock); |
582 | mutex_unlock(&src_as->lock); |
600 | interrupts_restore(ipl); |
583 | interrupts_restore(ipl); |
601 | return ENOENT; |
584 | return ENOENT; |
602 | } |
585 | } |
603 | - | ||
604 | 586 | ||
605 | if (!src_area->backend || !src_area->backend->share) { |
587 | if (!src_area->backend || !src_area->backend->share) { |
606 | /* |
588 | /* |
607 | * There is no backend or the backend does not |
589 | * There is no backend or the backend does not |
608 | * know how to share the area. |
590 | * know how to share the area. |
Line 615... | Line 597... | ||
615 | 597 | ||
616 | src_size = src_area->pages * PAGE_SIZE; |
598 | src_size = src_area->pages * PAGE_SIZE; |
617 | src_flags = src_area->flags; |
599 | src_flags = src_area->flags; |
618 | src_backend = src_area->backend; |
600 | src_backend = src_area->backend; |
619 | src_backend_data = src_area->backend_data; |
601 | src_backend_data = src_area->backend_data; |
620 | src_orig_color = src_area->orig_color; |
- | |
621 | 602 | ||
622 | /* Share the cacheable flag from the original mapping */ |
603 | /* Share the cacheable flag from the original mapping */ |
623 | if (src_flags & AS_AREA_CACHEABLE) |
604 | if (src_flags & AS_AREA_CACHEABLE) |
624 | dst_flags_mask |= AS_AREA_CACHEABLE; |
605 | dst_flags_mask |= AS_AREA_CACHEABLE; |
625 | 606 | ||
Line 628... | Line 609... | ||
628 | mutex_unlock(&src_as->lock); |
609 | mutex_unlock(&src_as->lock); |
629 | interrupts_restore(ipl); |
610 | interrupts_restore(ipl); |
630 | return EPERM; |
611 | return EPERM; |
631 | } |
612 | } |
632 | 613 | ||
- | 614 | #ifdef CONFIG_VIRT_IDX_DCACHE |
|
- | 615 | if (!(dst_flags_mask & AS_AREA_EXEC)) { |
|
- | 616 | if (PAGE_COLOR(src_area->base) != PAGE_COLOR(dst_base)) { |
|
- | 617 | /* |
|
- | 618 | * Refuse to create an illegal address alias. |
|
- | 619 | */ |
|
- | 620 | mutex_unlock(&src_area->lock); |
|
- | 621 | mutex_unlock(&src_as->lock); |
|
- | 622 | interrupts_restore(ipl); |
|
- | 623 | return ENOTSUP; |
|
- | 624 | } |
|
- | 625 | } |
|
- | 626 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
|
- | 627 | ||
633 | /* |
628 | /* |
634 | * Now we are committed to sharing the area. |
629 | * Now we are committed to sharing the area. |
635 | * First, prepare the area for sharing. |
630 | * First, prepare the area for sharing. |
636 | * Then it will be safe to unlock it. |
631 | * Then it will be safe to unlock it. |
637 | */ |
632 | */ |
Line 680... | Line 675... | ||
680 | */ |
675 | */ |
681 | mutex_lock(&dst_as->lock); |
676 | mutex_lock(&dst_as->lock); |
682 | mutex_lock(&dst_area->lock); |
677 | mutex_lock(&dst_area->lock); |
683 | dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL; |
678 | dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL; |
684 | dst_area->sh_info = sh_info; |
679 | dst_area->sh_info = sh_info; |
685 | dst_area->orig_color = src_orig_color; |
- | |
686 | #ifdef CONFIG_VIRT_IDX_DCACHE |
- | |
687 | if (src_orig_color != PAGE_COLOR(dst_base)) { |
- | |
688 | /* |
- | |
689 | * We have just detected an attempt to create an invalid address |
- | |
690 | * alias. We allow this and set a special flag that tells the |
- | |
691 | * architecture specific code to flush the D-cache when the |
- | |
692 | * offending address space is installed and deinstalled |
- | |
693 | * (cleanup). |
- | |
694 | * |
- | |
695 | * In order for the flags to take effect immediately, we also |
- | |
696 | * perform a global D-cache shootdown. |
- | |
697 | */ |
- | |
698 | dcache_shootdown_start(); |
- | |
699 | dst_as->dcache_flush_on_install = true; |
- | |
700 | dst_as->dcache_flush_on_deinstall = true; |
- | |
701 | dcache_flush(); |
- | |
702 | dcache_shootdown_finalize(); |
- | |
703 | } |
- | |
704 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
- | |
705 | mutex_unlock(&dst_area->lock); |
680 | mutex_unlock(&dst_area->lock); |
706 | mutex_unlock(&dst_as->lock); |
681 | mutex_unlock(&dst_as->lock); |
707 | 682 | ||
708 | interrupts_restore(ipl); |
683 | interrupts_restore(ipl); |
709 | 684 |