static void __cpuinit build_r4000_tlb_modify_handler(void) { u32 *p = handle_tlbm; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; memset(handle_tlbm, 0, sizeof(handle_tlbm)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); /* Present and writable bits set, set accessed and dirty bits. */ build_make_write(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); uasm_l_nopage_tlbm(&l, p); uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); if ((p - handle_tlbm) > FASTPATH_SIZE) panic("TLB modify handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbm)); dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); }
static void __cpuinit build_r3000_tlb_modify_handler(void) { u32 *p = handle_tlbm; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; memset(handle_tlbm, 0, sizeof(handle_tlbm)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); uasm_i_nop(&p); /* load delay */ build_make_write(&p, &r, K0, K1); build_r3000_pte_reload_tlbwi(&p, K0, K1); uasm_l_nopage_tlbm(&l, p); uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); if ((p - handle_tlbm) > FASTPATH_SIZE) panic("TLB modify handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbm)); dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); }
pid_t handle_events_until_dump_trap(pid_t wait_for) { while (true) { event_t e = wait_event(wait_for); if (e.signo == SIGTRAP) { if (is_dump_sigtrap(e.tid)) { clear_trap(e.tid); return e.tid; } else if (is_hook_sigtrap(e.tid)) { assert(tracer_state == TRACER_LOCKED || tracer_state == TRACER_FIRSTTOUCH); clear_trap(e.tid); tracer_lock_range(e.tid); continue; } else { // If we arrive here, it is a syscall handle_syscall(e.tid); ptrace_syscall(e.tid); continue; } } else if (e.signo == SIGSEGV) { void *addr = round_to_page(e.sigaddr); switch (tracer_state) { case TRACER_UNLOCKED: /* We should never get a sigsegv in unlocked state ! */ errx(EXIT_FAILURE, "SIGSEGV at %p before locking memory during capture\n", e.sigaddr); case TRACER_FIRSTTOUCH: firsttouch_handler(e.tid, addr); break; case TRACER_LOCKED: mru_handler(e.tid, addr); break; case TRACER_DUMPING: dump_handler(e.tid, addr); break; default: assert(false); /* we should never be here */ } ptrace_syscall(e.tid); } else if (e.signo == SIGSTOP) { /* A new thread is starting, ignore this event, next wait_event call will unblock the thread once its parents registers it in tids array */ } else if (e.signo == SIGWINCH) { /* Ignore signal SIGWINCH, tty resize */ ptrace_syscall(e.tid); continue; } else { errx(EXIT_FAILURE, "Unexpected signal in wait_sigtrap: %d\n", e.signo); } } debug_print("%s", "\n"); }
static void __cpuinit build_r4000_tlb_load_handler(void) { u32 *p = handle_tlbl; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; memset(handle_tlbl, 0, sizeof(handle_tlbl)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); if (bcm1250_m3_war()) { UASM_i_MFC0(&p, K0, C0_BADVADDR); UASM_i_MFC0(&p, K1, C0_ENTRYHI); uasm_i_xor(&p, K0, K0, K1); UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1); uasm_il_bnez(&p, &r, K0, label_leave); /* No need for uasm_i_nop */ } build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); if (m4kc_tlbp_war()) build_tlb_probe_entry(&p); build_make_valid(&p, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); uasm_l_nopage_tlbl(&l, p); uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); uasm_i_nop(&p); if ((p - handle_tlbl) > FASTPATH_SIZE) panic("TLB load handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbl)); dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); }
/* * The R3000 TLB handler is simple. */ static void __cpuinit build_r3000_tlb_refill_handler(void) { long pgdc = (long)pgd_current; u32 *p; memset(tlb_handler, 0, sizeof(tlb_handler)); p = tlb_handler; uasm_i_mfc0(&p, K0, C0_BADVADDR); uasm_i_lui(&p, K1, uasm_rel_hi(pgdc)); /* cp0 delay */ uasm_i_lw(&p, K1, uasm_rel_lo(pgdc), K1); uasm_i_srl(&p, K0, K0, 22); /* load delay */ uasm_i_sll(&p, K0, K0, 2); uasm_i_addu(&p, K1, K1, K0); uasm_i_mfc0(&p, K0, C0_CONTEXT); uasm_i_lw(&p, K1, 0, K1); /* cp0 delay */ uasm_i_andi(&p, K0, K0, 0xffc); /* load delay */ uasm_i_addu(&p, K1, K1, K0); uasm_i_lw(&p, K0, 0, K1); uasm_i_nop(&p); /* load delay */ uasm_i_mtc0(&p, K0, C0_ENTRYLO0); uasm_i_mfc0(&p, K1, C0_EPC); /* cp0 delay */ uasm_i_tlbwr(&p); /* cp0 delay */ uasm_i_jr(&p, K1); uasm_i_rfe(&p); /* branch delay */ if (p > tlb_handler + 32) panic("TLB refill handler space exceeded"); pr_debug("Wrote TLB refill handler (%u instructions).\n", (unsigned int)(p - tlb_handler)); memcpy((void *)ebase, tlb_handler, 0x80); dump_handler((u32 *)ebase, 32); }