STRUCT EMUFRAME(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct emuframe(9) β€” like, the emulation frame struct, bestie

okay so this is straight out of the Kernel API Manual, section 9, and it's about this lil' struct emuframe β€” the frame that makes delay-slot emulation on MIPS actually work. no cap, it's lowkey iconic. πŸŽ€


✨ NAME ✨

struct emuframe β€” the "emulation" frame structure. that's it, that's the vibe. πŸ¦‹


🧚 SYNOPSIS 🧚

here's the shape of it, copy-paste exact bc we do not mess with literal code:

struct emuframe {
    mips_instruction emul;
    mips_instruction badinst;
 };

🌸 Members 🌸

  • emul β€” the instruction we're gonna 'emulate'. that's the whole assignment, bestie. πŸ‘‘
  • badinst β€” a break instruction, and its only job is to cause a return to the kernel. πŸ’«

πŸ’– Description πŸ’–

okay so picture this: this structure defines the frames that get placed within the delay slot emulation page whenever someone calls mips_dsemul. and here's the thing β€” each thread may be allocated only one frame at any given time. one. that's it. no hoarding. πŸ™ˆ

what the kernel does is stash inside the frame the instruction to be 'emulated', followed by a break instruction, and then it executes the frame in user mode. and then? the break causes a trap to the kernel, which leads to do_dsemulret being called β€” unless the instruction in emul causes a trap itself, or is a branch, or a signal gets delivered to the thread. 😭 in those cases the allocated frame will either be reused by a subsequent delay slot 'emulation', or freed during signal delivery or upon thread exit. so it's not leaking, it's just chillin' till it's needed again. periodt.

so why even do it this way? glad you asked, because the reasoning is genuinely tea:

  • actually emulating all instructions isn't feasible. fr fr β€” we'd need to be able to handle instructions from all revisions of the MIPS ISA, all ASEs & all vendor instruction set extensions. that's a whole lot of work & a continual maintenance burden as new instructions keep getting introduced, and in the case of some vendor extensions it may not even be possible. so nope, we take the approach of actually executing the instruction. πŸ’€
  • we must execute the instruction within user context. because if we executed it in kernel mode, it would have access to kernel resources without very careful checks, leaving us with a high potential for security or stability issues to arise. and we don't do that here. 🚩
  • we used to place the frame on the users stack, but that requires the stack to be executable. that's bad for security, so the per-process page is now used instead. glow-up, honestly. ✨
  • the instruction in emul may be something entirely invalid for a delay slot. the user may (intentionally or otherwise) place a branch in a delay slot, or a kernel mode instruction, or something else which generates an exception. so we can't rely upon the break in badinst always being hit. for this reason we track the index of the frame allocated to each thread, letting us clean it up at later points such as signal delivery or thread exit. tracking = self-care. πŸ’…
  • the user may generate a fake struct emuframe if they wish, invoking the BRK_MEMU break instruction themselves. so we must not trust that BRK_MEMU means there's actually a valid frame allocated to the thread, and we must not allow the user to do anything they couldn't already. trust issues, but make it kernel security. πŸ”₯
bestie warning 🫢: that last one is the spicy one β€” never assume BRK_MEMU implies a real frame exists. that's the whole point of the last bullet, and skipping it is a one-way ticket to vulnerability city.

🌈 SEE ALSO 🌈

  • Kernel file ./arch/mips/math-emu/dsemul.c β€” go read it, it's giving main character energy. πŸ“–

aaaand that's the page!! source path is ./arch/mips/math-emu and it's dated October 2026 β€” so like, future-dated slay. bye bestie, go emulate responsibly πŸ’œπŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from