ICEBP Finally Documented

After more than 30 years, Intel finally documented the INT1 instruction, also known as ICEBP (opcode F1h), in the latest (May 2018, -067) edition of the SDM. This was probably forced by security concerns, because from a security standpoint, having undocumented instructions which trigger special interrupts from user mode is insane, and Intel does not need more bad press than it already has.

The situation was fairly ridiculous, with most system software developers well aware of what ICEBP does, despite Intel’s abject failure to document what has been a part of the x86 architecture since the 386 (released in 1985). It helped that AMD’s 64-bit architecture manuals provided enough information about INT1/ICEBP for well over a decade.

Things got doubly ridiculous when Intel’s hardware virtualization (VT-x) documentation needed to talk about a “privileged software exception” without providing the slightest hint how such a mysterious thing might happen (why yes, executing ICEBP!). That, predictably, caused problems.

To recap, INT1 aka ICEBP (opcode F1h) is a single-byte breakpoint instruction similar to INT3 (opcode CCh), with the interesting property that it does not set any bits in DR6 and triggers a #DB exception without any privilege checks. It is intended for use with hardware debuggers (In-Circuit Emulators or ICEs) and conceptually behaves much like a software-triggered unmaskable hardware interrupt. That is why it needs to be handled specially by hypervisors, because it’s not quite like other exceptions and not quite like a hardware interrupt. It is however perfectly usable by software debuggers with no ICE in sight. System-level debuggers may even prefer using ICEBP to avoid conflicts with application-level debuggers.

Documenting an instruction after more than 30 years might, or at least should, be a world record. Intel is expected to break its own record once it fully documents the SALC instruction (opcode D6h), which has been with us since 1978 (introduced in the 8086). For decades Intel pretended SALC does not exist, in recent SDM editions the instruction is mentioned by name together with its opcode and a brief description, but not documented in the instruction reference and left out of the opcode map.

This entry was posted in 386, Documentation, Intel, Undocumented. Bookmark the permalink.

14 Responses to ICEBP Finally Documented

  1. dosfan says:

    I noticed they also changed “INT 3” (with a space) to “INT3” (without a space).

    Are there any undocumented instructions left now ? They mention all of the opcode duplicates and FFREEP in the SDM Volume 3 now.

    Is it known why Intel never officially documented SALC ?

  2. Michal Necasek says:

    Yes, the “INT 3” -> “INT3” change was very invasive. I’m surprised they used to spell it with a space. I know some assemblers distinguish between the two (INT3 -> CCh, INT 3 -> CDh 03h), and it’s a very useful way to make it clear what’s what, because the behavior is not the same.

    I have no idea why Intel never documented SALC. You’d think that after 10-20 years they would make up their damn mind and either remove the instruction or document it.

  3. Richard Wells says:

    SALC only seems to make sense for code ported from the 8080. The flag register was the lower byte paired with the accumulator as the program status word. Code that used the PSW as an entity could instead be translated to having the accumulator in AH and SALC putting the only flag that mattered in AL. (If SALC wasn’t a buggy implementation that should have instead extracted the 8080’s 8 flags out of the 8086’s dozen flags.)

    With the number of instruction in x86 that require values stored in AX or EAX, SALC might prove counterproductive since it resets AL to 0 if the carry flag didn’t get tripped. SALC precludes using any optimization that retains a value in AL, AX, or EAX.

    I think Intel is stuck on this. Too much existing code knows about SALC and will break if it is removed. Documenting SALC would result in a lot of slower or buggy code as programmers that don’t understand the interactions try it out.

  4. Michal Necasek says:

    That sort of reasoning made sense 30 years ago I’m sure, but today it doesn’t fly. Consider the fact that all the bad guys writing malware can find information about SALC. If anti-malware cannot properly analyze code using SALC because it is not fully documented, that is a problem. So at best Intel is refusing to document something that everyone already knows anyway, at worst Intel is actively helping malware authors.

    I think you’re right that Intel never removed SALC because it’s used too much — relatively rarely in fact, but just enough that removing it would cause problems. But if Intel documented SALC properly, the only people who would use SALC are probably the ones already using it. It’s not like a lot of code is written in assembler, and in 64-bit mode SALC does not exist anyway.

  5. deater says:

    I wonder if the sandsifter work has in any way prodded intel to finally document things.

    Did they ever release which processor it was that had the previously unknown halt-and-catch-fire instruction?

  6. Michal Necasek says:

    No word on the halt-and-catch-fire instruction. A bit suspicious really. The rest was very unspectacular, mostly undocumented NOPs.

  7. Octocontrabass says:

    Speaking of undocumented things (yes, this is a bit of a non-sequitur but I’m afraid if I put it on a more relevant older post I’ll forget about it!), I’ve recently discovered some old AMI BIOSes use SMSW to differentiate between a 386 and a 486. Turns out, the reserved bits in CR0 are always set on a 386.

    I wrote a test program, in case you’re interested in seeing the actual register values on your own PCs: https://github.com/jeffpar/pcjs/files/2043131/id.zip

  8. Yuhong Bao says:

    SMSW has the benefit that virtual 8086 mode hypervisors can’t trap it, unlike PUSHF/POPF.

  9. Michal Necasek says:

    Interesting. This indeed appears to be undocumented, Intel only hints at the difference–the 486 datasheet clearly gives the CR0 reset value as 60000000h, while the 386 datasheet gives it as UUUUUUU0h, with all the high bits “undefined”. Are the reserved bits actually always set on a 386, or only after a reset?

  10. Octocontrabass says:

    The test program above tries to clear CR0, and on both of my 386-based test machines CR0 has the value 0x7FFFFFE0 afterwards.

  11. Michal Necasek says:

    Are those both 386DX chips? I think the value ought to be different on a 386SX.

    At any rate, that certainly sounds like the reserved bits are all hardwired to 1. One of the far too many instances where Intel documents things as “undefined” when they’re not really.

  12. Octocontrabass says:

    Yeah, they’re both 386DX. I don’t have a 386SX, and no one who does has run the program yet.

  13. Jeff says:

    Regarding the CR0 behavior, I saw the same thing as @Octocontrabass on my DeskPro 386/25. I posted a screenshot in the PCjs bug report.

  14. Yuhong Bao says:

    Interestingly, the 80386 manual is incorrect on this topic:
    https://pdos.csail.mit.edu/6.828/2017/readings/i386/s14_08.htm

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.