/* * It's not generally safe to use "current" to get the page table pointer, * since we might be running an oprofile interrupt in the middle of a * task switch. */ static pgd_t *get_current_pgd(void) { HV_Context ctx = hv_inquire_context(); unsigned long pgd_pfn = ctx.page_table >> PAGE_SHIFT; struct page *pgd_page = pfn_to_page(pgd_pfn); BUG_ON(PageHighMem(pgd_page)); /* oops, HIGHPTE? */ return (pgd_t *) __va(ctx.page_table); }
void KBacktraceIterator_init(struct KBacktraceIterator *kbt, struct task_struct *t, struct pt_regs *regs) { unsigned long pc, lr, sp, r52; int is_current; /* * Set up callback information. We grab the kernel stack base * so we will allow reads of that address range, and if we're * asking about the current process we grab the page table * so we can check user accesses before trying to read them. * We flush the TLB to avoid any weird skew issues. */ is_current = (t == NULL); kbt->is_current = is_current; if (is_current) t = validate_current(); kbt->task = t; kbt->pgtable = NULL; kbt->verbose = 0; /* override in caller if desired */ kbt->profile = 0; /* override in caller if desired */ kbt->end = KBT_ONGOING; kbt->new_context = 0; if (is_current) { HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; if (pgdir_pa == (unsigned long)swapper_pg_dir - PAGE_OFFSET) { /* * Not just an optimization: this also allows * this to work at all before va/pa mappings * are set up. */ kbt->pgtable = swapper_pg_dir; } else { struct page *page = pfn_to_page(PFN_DOWN(pgdir_pa)); if (!PageHighMem(page)) kbt->pgtable = __va(pgdir_pa); else pr_err("page table not in LOWMEM" " (%#llx)\n", pgdir_pa); } local_flush_tlb_all(); validate_stack(regs); } if (regs == NULL) { if (is_current || t->state == TASK_RUNNING) { /* Can't do this; we need registers */ kbt->end = KBT_RUNNING; return; } pc = get_switch_to_pc(); lr = t->thread.pc; sp = t->thread.ksp; r52 = 0; } else { pc = regs->pc; lr = regs->lr; sp = regs->sp; r52 = regs->regs[52]; } backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52); kbt->end = KBacktraceIterator_next_item_inclusive(kbt); }