static int copy_locked(void __user *uptr, void *kptr, size_t size, int write, void (*copyfn)(void *, void __user *)) { unsigned char v, __user *userptr = uptr; int err = 0; do { struct mm_struct *mm; if (write) { __put_user_error(0, userptr, err); __put_user_error(0, userptr + size - 1, err); } else { __get_user_error(v, userptr, err); __get_user_error(v, userptr + size - 1, err); } if (err) break; mm = current->mm; spin_lock(&mm->page_table_lock); if (page_present(mm, userptr, write) && page_present(mm, userptr + size - 1, write)) { copyfn(kptr, uptr); } else err = 1; spin_unlock(&mm->page_table_lock); } while (err); return err; }
void handle_tlb_miss(struct cpu_regs *regs) { uint32_t esr, dear; pgd_t pgd = mmu_get_current_pgd(); esr = mfspr(SPR_ESR); dear = mfspr(SPR_DEAR); /* * Search on current page global directory */ if (pte_present(pgd, dear)) { /* get page table entry from given fault address */ pte_t pte = vtopte(pgd, dear); if (page_present(pte, dear)) { mmu_replace_tlb_entry(dear, (paddr_t)ptetopg(pte, dear), pte); return; } } panic("Access denied\n"); }
bt_paddr_t bt_mmu_extract(bt_pgd_t pgd_h, bt_vaddr_t virt, BT_u32 size) { bt_pte_t pte; bt_vaddr_t start, end, pg; bt_paddr_t pa; bt_pgd_t pgd = GET_PGD(pgd_h); start = BT_PAGE_TRUNC(virt); end = BT_PAGE_TRUNC(virt+size-1); // Check all pages exist. for(pg = start; pg <= end; pg += BT_PAGE_SIZE) { if(!pte_present(pgd, pg)) { return 0; } pte = virt_to_pte(pgd, pg); if(!page_present(pte, pg)) { return 0; } } pte = virt_to_pte(pgd, start); pa = (bt_paddr_t) pte_to_phys(pte, start); return pa + (bt_paddr_t) (virt - start); }