Rev 2787 | Rev 3036 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2787 | Rev 3013 | ||
---|---|---|---|
Line 959... | Line 959... | ||
959 | spinlock_unlock(&asidlock); |
959 | spinlock_unlock(&asidlock); |
960 | 960 | ||
961 | AS = new_as; |
961 | AS = new_as; |
962 | } |
962 | } |
963 | 963 | ||
- | 964 | /** Write directly into a page, bypassing area flags. |
|
- | 965 | * |
|
- | 966 | * This allows a debugger to write into a page that is mapped read-only |
|
- | 967 | * (such as the text segment). Naturally, this is only possible if the |
|
- | 968 | * correspoinding area is not shared and anonymous. |
|
- | 969 | * |
|
- | 970 | * FIXME: doesn't take into account that it isn't a good idea to write |
|
- | 971 | * into the frame if the area is shared or isn't anonymous |
|
- | 972 | */ |
|
- | 973 | static int debug_write_inside_page(uintptr_t va, void *data, size_t n) |
|
- | 974 | { |
|
- | 975 | uintptr_t page; |
|
- | 976 | pte_t *pte; |
|
- | 977 | as_area_t *area; |
|
- | 978 | uintptr_t frame; |
|
- | 979 | ipl_t ipl; |
|
- | 980 | int rc; |
|
- | 981 | ||
- | 982 | page = ALIGN_DOWN(va, PAGE_SIZE); |
|
- | 983 | ASSERT(ALIGN_DOWN(va + n - 1, PAGE_SIZE) == page); |
|
- | 984 | ||
- | 985 | restart: |
|
- | 986 | mutex_lock(&AS->lock); |
|
- | 987 | ipl = interrupts_disable(); |
|
- | 988 | area = find_area_and_lock(AS, page); |
|
- | 989 | ||
- | 990 | pte = page_mapping_find(AS, page); |
|
- | 991 | if (! (pte && PTE_VALID(pte) && PTE_PRESENT(pte)) ) { |
|
- | 992 | mutex_unlock(&area->lock); |
|
- | 993 | mutex_unlock(&AS->lock); |
|
- | 994 | interrupts_restore(ipl); |
|
- | 995 | ||
- | 996 | rc = as_page_fault(page, PF_ACCESS_WRITE, NULL); |
|
- | 997 | if (rc == AS_PF_FAULT) return EINVAL; |
|
- | 998 | ||
- | 999 | goto restart; |
|
- | 1000 | } |
|
- | 1001 | ||
- | 1002 | frame = PTE_GET_FRAME(pte); |
|
- | 1003 | memcpy((void *)(PA2KA(frame) + (va - page)), data, n); |
|
- | 1004 | ||
- | 1005 | mutex_unlock(&area->lock); |
|
- | 1006 | mutex_unlock(&AS->lock); |
|
- | 1007 | interrupts_restore(ipl); |
|
- | 1008 | ||
- | 1009 | return EOK; |
|
- | 1010 | } |
|
- | 1011 | ||
- | 1012 | /** Write data bypassing area flags. |
|
- | 1013 | * |
|
- | 1014 | * See debug_write_inside_page(). |
|
- | 1015 | */ |
|
- | 1016 | int as_debug_write(uintptr_t va, void *data, size_t n) |
|
- | 1017 | { |
|
- | 1018 | size_t now; |
|
- | 1019 | int rc; |
|
- | 1020 | ||
- | 1021 | while (n > 0) { |
|
- | 1022 | now = ALIGN_UP(va, PAGE_SIZE) - va; |
|
- | 1023 | if (now > n) now = n; |
|
- | 1024 | ||
- | 1025 | rc = debug_write_inside_page(va, data, now); |
|
- | 1026 | if (rc != EOK) return rc; |
|
- | 1027 | ||
- | 1028 | va += now; |
|
- | 1029 | data += now; |
|
- | 1030 | n -= now; |
|
- | 1031 | } |
|
- | 1032 | ||
- | 1033 | return EOK; |
|
- | 1034 | } |
|
- | 1035 | ||
964 | /** Convert address space area flags to page flags. |
1036 | /** Convert address space area flags to page flags. |
965 | * |
1037 | * |
966 | * @param aflags Flags of some address space area. |
1038 | * @param aflags Flags of some address space area. |
967 | * |
1039 | * |
968 | * @return Flags to be passed to page_mapping_insert(). |
1040 | * @return Flags to be passed to page_mapping_insert(). |