staticint alloc_emuframe(void)
{
mm_context_t *mm_ctx = ¤t->mm->context; int idx;
retry:
spin_lock(&mm_ctx->bd_emupage_lock);
/* Ensure we have an allocation bitmap */ if (!mm_ctx->bd_emupage_allocmap) {
mm_ctx->bd_emupage_allocmap = bitmap_zalloc(emupage_frame_count,
GFP_ATOMIC); if (!mm_ctx->bd_emupage_allocmap) {
idx = BD_EMUFRAME_NONE; goto out_unlock;
}
}
/* Attempt to allocate a single bit/frame */
idx = bitmap_find_free_region(mm_ctx->bd_emupage_allocmap,
emupage_frame_count, 0); if (idx < 0) { /* *Failedtoallocateaframe.We'llwaituntilonebecomes *available.Weunlockthepagesothatotherthreadsactually *gettheopportunitytofreetheirframes,whichmeans *technicallytheresultofbitmap_fullmaybeincorrect. *Howevertheworstcaseisthatwerepeatallthisandendup *backhereagain.
*/
spin_unlock(&mm_ctx->bd_emupage_lock); if (!wait_event_killable(mm_ctx->bd_emupage_queue,
!bitmap_full(mm_ctx->bd_emupage_allocmap,
emupage_frame_count))) goto retry;
/* Received a fatal signal - just give in */ return BD_EMUFRAME_NONE;
}
pr_debug("dsemul 0x%08lx cont at 0x%08lx\n", regs->cp0_epc, cont_pc);
/* Allocate a frame if we don't already have one */
fr_idx = atomic_read(¤t->thread.bd_emu_frame); if (fr_idx == BD_EMUFRAME_NONE)
fr_idx = alloc_emuframe(); if (fr_idx == BD_EMUFRAME_NONE) return SIGBUS;
/* Write the instructions to the frame */ if (isa16) { union mips_instruction _emul = {
.halfword = { ir >> 16, ir }
}; union mips_instruction _badinst = {
.halfword = { break_math >> 16, break_math }
};
/* Write the frame to user memory */
fr_uaddr = (unsignedlong)&dsemul_page()[fr_idx];
ret = access_process_vm(current, fr_uaddr, &fr, sizeof(fr),
FOLL_FORCE | FOLL_WRITE); if (unlikely(ret != sizeof(fr))) {
MIPS_FPU_EMU_INC_STATS(errors);
free_emuframe(fr_idx, current->mm); return SIGBUS;
}
/* Record the PC of the branch, PC to continue from & frame index */
current->thread.bd_emu_branch_pc = branch_pc;
current->thread.bd_emu_cont_pc = cont_pc;
atomic_set(¤t->thread.bd_emu_frame, fr_idx);
/* Change user register context to execute the frame */
regs->cp0_epc = fr_uaddr | isa16;
return0;
}
bool do_dsemulret(struct pt_regs *xcp)
{ /* Cleanup the allocated frame, returning if there wasn't one */ if (!dsemul_thread_cleanup(current)) {
MIPS_FPU_EMU_INC_STATS(errors); returnfalse;
}
/* Set EPC to return to post-branch instruction */
xcp->cp0_epc = current->thread.bd_emu_cont_pc;
pr_debug("dsemulret to 0x%08lx\n", xcp->cp0_epc);
MIPS_FPU_EMU_INC_STATS(ds_emul); returntrue;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.