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 | } |