Rev 2009 | Rev 2069 | 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 | ||