/* * This function checks all page tables of "current" */ void check_page_tables (void) { struct pgd *pg_dir; static int err = 0; int stack_level = (long) (&pg_dir) - current->kernel_stack_page; if (stack_level < 1500) printk ("** %d ** ", stack_level); pg_dir = PAGE_DIR_OFFSET (current, 0); if (err == 0) { int i; for (i = 0; i < PTRS_PER_PAGE; i++, page_dir++) { int notok = check_one_table (page_dir); if (notok) { err++; printk ("|%d:%08lx| ", i, page_dir->pgd); } } if (err) printk ("\nError MM %d\n", err); } }
/* * This routine gets a long from any process space by following the page * tables. NOTE! You should check that the long isn't on a page boundary, * and that it is in the task area before calling this: this routine does * no checking. */ static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr) { pgd_t * pgdir; pte_t * pgtable; unsigned long page; repeat: pgdir = PAGE_DIR_OFFSET(vma->vm_mm, addr); if (pgd_none(*pgdir)) { do_no_page(vma, addr, 0); goto repeat; } if (pgd_bad(*pgdir)) { printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); pgd_clear(pgdir); return 0; } pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); if (!pte_present(*pgtable)) { do_no_page(vma, addr, 0); goto repeat; } page = pte_page(*pgtable); /* this is a hack for non-kernel-mapped video buffers and similar */ if (page >= high_memory) return 0; page += addr & ~PAGE_MASK; return *(unsigned long *) page; }
static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr) { unsigned long page; if (!p || !*p || ptr >= TASK_SIZE) return 0; page = *PAGE_DIR_OFFSET((*p)->tss.cr3,ptr); if (!(page & 1)) return 0; page &= PAGE_MASK; page += PAGE_PTR(ptr); page = *(unsigned long *) page; if (!(page & 1)) return 0; page &= PAGE_MASK; page += ptr & ~PAGE_MASK; return page; }
/* * This routine puts a long into any process space by following the page * tables. NOTE! You should check that the long isn't on a page boundary, * and that it is in the task area before calling this: this routine does * no checking. * * Now keeps R/W state of page so that a text page stays readonly * even if a debugger scribbles breakpoints into it. -M.U- */ static void put_long(struct vm_area_struct * vma, unsigned long addr, unsigned long data) { pgd_t *pgdir; pte_t *pgtable; unsigned long page; repeat: pgdir = PAGE_DIR_OFFSET(vma->vm_task, addr); if (!pgd_present(*pgdir)) { do_no_page(vma, addr, 1); goto repeat; } if (pgd_bad(*pgdir)) { printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); pgd_clear(pgdir); return; } pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); if (!pte_present(*pgtable)) { do_no_page(vma, addr, 1); goto repeat; } page = pte_page(*pgtable); if (!pte_write(*pgtable)) { do_wp_page(vma, addr, 1); goto repeat; } /* this is a hack for non-kernel-mapped video buffers and similar */ if (page < high_memory) { page += addr & ~PAGE_MASK; *(unsigned long *) page = data; } /* we're bypassing pagetables, so we have to set the dirty bit ourselves */ /* this should also re-instate whatever read-only mode there was before */ *pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot)); invalidate(); }