Rev 2927 | Rev 2985 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2927 | Rev 2984 | ||
|---|---|---|---|
| Line 773... | Line 773... | ||
| 773 | return false; |
773 | return false; |
| 774 | 774 | ||
| 775 | return true; |
775 | return true; |
| 776 | } |
776 | } |
| 777 | 777 | ||
| - | 778 | /** Change adress area flags. |
|
| - | 779 | * |
|
| - | 780 | * The idea is to have the same data, but with a different access mode. |
|
| - | 781 | * This is needed e.g. for writing code into memory and then executing it. |
|
| - | 782 | * In order for this to work properly, this may copy the data |
|
| - | 783 | * into private anonymous memory (unless it's already there). |
|
| - | 784 | * |
|
| - | 785 | * @param as Address space. |
|
| - | 786 | * @param flags Flags of the area memory. |
|
| - | 787 | * @param address Address withing the area to be changed. |
|
| - | 788 | * |
|
| - | 789 | * @return Zero on success or a value from @ref errno.h on failure. |
|
| - | 790 | */ |
|
| - | 791 | int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
|
| - | 792 | { |
|
| - | 793 | as_area_t *area; |
|
| - | 794 | uintptr_t base; |
|
| - | 795 | link_t *cur; |
|
| - | 796 | ipl_t ipl; |
|
| - | 797 | ||
| - | 798 | ipl = interrupts_disable(); |
|
| - | 799 | mutex_lock(&as->lock); |
|
| - | 800 | ||
| - | 801 | area = find_area_and_lock(as, address); |
|
| - | 802 | if (!area) { |
|
| - | 803 | mutex_unlock(&as->lock); |
|
| - | 804 | interrupts_restore(ipl); |
|
| - | 805 | return ENOENT; |
|
| - | 806 | } |
|
| - | 807 | ||
| - | 808 | if (area->sh_info || area->backend != &anon_backend) { |
|
| - | 809 | /* Copying shared areas not supported yet */ |
|
| - | 810 | /* Copying non-anonymous memory not supported yet */ |
|
| - | 811 | mutex_unlock(&as->lock); |
|
| - | 812 | interrupts_restore(ipl); |
|
| - | 813 | return ENOTSUP; |
|
| - | 814 | } |
|
| - | 815 | ||
| - | 816 | base = area->base; |
|
| - | 817 | ||
| - | 818 | /* |
|
| - | 819 | * Start TLB shootdown sequence. |
|
| - | 820 | */ |
|
| - | 821 | tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages); |
|
| - | 822 | ||
| - | 823 | /* |
|
| - | 824 | * Visit only the pages mapped by used_space B+tree. |
|
| - | 825 | */ |
|
| - | 826 | for (cur = area->used_space.leaf_head.next; |
|
| - | 827 | cur != &area->used_space.leaf_head; cur = cur->next) { |
|
| - | 828 | btree_node_t *node; |
|
| - | 829 | unsigned int i; |
|
| - | 830 | ||
| - | 831 | node = list_get_instance(cur, btree_node_t, leaf_link); |
|
| - | 832 | for (i = 0; i < node->keys; i++) { |
|
| - | 833 | uintptr_t b = node->key[i]; |
|
| - | 834 | count_t j; |
|
| - | 835 | pte_t *pte; |
|
| - | 836 | ||
| - | 837 | for (j = 0; j < (count_t) node->value[i]; j++) { |
|
| - | 838 | page_table_lock(as, false); |
|
| - | 839 | pte = page_mapping_find(as, b + j * PAGE_SIZE); |
|
| - | 840 | ASSERT(pte && PTE_VALID(pte) && |
|
| - | 841 | PTE_PRESENT(pte)); |
|
| - | 842 | ||
| - | 843 | /* Remove old mapping and insert the new one */ |
|
| - | 844 | page_mapping_remove(as, b + j * PAGE_SIZE); |
|
| - | 845 | page_mapping_insert(as, b + j * PAGE_SIZE, |
|
| - | 846 | PTE_GET_FRAME(pte), flags); |
|
| - | 847 | page_table_unlock(as, false); |
|
| - | 848 | } |
|
| - | 849 | } |
|
| - | 850 | } |
|
| - | 851 | ||
| - | 852 | /* |
|
| - | 853 | * Finish TLB shootdown sequence. |
|
| - | 854 | */ |
|
| - | 855 | ||
| - | 856 | tlb_invalidate_pages(as->asid, area->base, area->pages); |
|
| - | 857 | /* |
|
| - | 858 | * Invalidate potential software translation caches (e.g. TSB on |
|
| - | 859 | * sparc64). |
|
| - | 860 | */ |
|
| - | 861 | as_invalidate_translation_cache(as, area->base, area->pages); |
|
| - | 862 | tlb_shootdown_finalize(); |
|
| - | 863 | ||
| - | 864 | mutex_unlock(&area->lock); |
|
| - | 865 | mutex_unlock(&as->lock); |
|
| - | 866 | interrupts_restore(ipl); |
|
| - | 867 | ||
| - | 868 | return 0; |
|
| - | 869 | } |
|
| - | 870 | ||
| - | 871 | ||
| 778 | /** Handle page fault within the current address space. |
872 | /** Handle page fault within the current address space. |
| 779 | * |
873 | * |
| 780 | * This is the high-level page fault handler. It decides |
874 | * This is the high-level page fault handler. It decides |
| 781 | * whether the page fault can be resolved by any backend |
875 | * whether the page fault can be resolved by any backend |
| 782 | * and if so, it invokes the backend to resolve the page |
876 | * and if so, it invokes the backend to resolve the page |
| Line 1768... | Line 1862... | ||
| 1768 | unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags) |
1862 | unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags) |
| 1769 | { |
1863 | { |
| 1770 | return (unative_t) as_area_resize(AS, address, size, 0); |
1864 | return (unative_t) as_area_resize(AS, address, size, 0); |
| 1771 | } |
1865 | } |
| 1772 | 1866 | ||
| - | 1867 | /** Wrapper for as_area_change_flags(). */ |
|
| - | 1868 | unative_t sys_as_area_change_flags(uintptr_t address, int flags) |
|
| - | 1869 | { |
|
| - | 1870 | return (unative_t) as_area_change_flags(AS, flags, address); |
|
| - | 1871 | } |
|
| - | 1872 | ||
| 1773 | /** Wrapper for as_area_destroy(). */ |
1873 | /** Wrapper for as_area_destroy(). */ |
| 1774 | unative_t sys_as_area_destroy(uintptr_t address) |
1874 | unative_t sys_as_area_destroy(uintptr_t address) |
| 1775 | { |
1875 | { |
| 1776 | return (unative_t) as_area_destroy(AS, address); |
1876 | return (unative_t) as_area_destroy(AS, address); |
| 1777 | } |
1877 | } |