With opcode D6h now firmly reserved as another #UD-raising one in 64-bit mode, use that instead of the two-byte UD2 for bug frame marking.
While there also make the respective adjustment to the emulator. Signed-off-by: Jan Beulich <[email protected]> --- Should we also switch {svm,vmx}_init_hypercall_page()? Furthermore x86_64/kexec_reloc.S also has two uses. Question is whether "tailcall" is being open-coded there, or whether that's deliberately not using the macro we have. One of the table entries in stub_selftest() uses UD1, yet not in quite an appropriate way: The 0x90 following it (presumably meant to be a NOP) really is a ModR/M byte, requiring a displacement to follow. Wouldn't we better adjust that (e.g. using 0xcc instead)? --- v9: New. --- a/xen/arch/x86/include/asm/bug.h +++ b/xen/arch/x86/include/asm/bug.h @@ -21,7 +21,7 @@ #ifndef __ASSEMBLY__ -#define BUG_INSTR "ud2" +#define BUG_INSTR ".byte 0xd6" /* UDB */ #define BUG_ASM_CONST "c" #else /* !__ASSEMBLY__ */ @@ -37,7 +37,7 @@ .error "Invalid BUGFRAME index" .endif - .L\@ud: ud2a + .L\@ud: .byte 0xd6 /* UDB */ .pushsection .rodata.str1, "aMS", @progbits, 1 .L\@s1: .asciz "\file_str" --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1256,7 +1256,7 @@ void asmlinkage do_trap(struct cpu_user_ void asmlinkage do_invalid_op(struct cpu_user_regs *regs) { - u8 bug_insn[2]; + uint8_t bug_insn; const void *eip = (const void *)regs->rip; int id; @@ -1268,8 +1268,8 @@ void asmlinkage do_invalid_op(struct cpu } if ( !is_active_kernel_text(regs->rip) || - copy_from_unsafe(bug_insn, eip, sizeof(bug_insn)) || - memcmp(bug_insn, "\xf\xb", sizeof(bug_insn)) ) + copy_from_unsafe(&bug_insn, eip, sizeof(bug_insn)) || + bug_insn != 0xd6 /* UDB */ ) goto die; id = do_bug_frame(regs, regs->rip); --- a/xen/arch/x86/x86_emulate/decode.c +++ b/xen/arch/x86/x86_emulate/decode.c @@ -651,7 +651,7 @@ decode_onebyte(struct x86_emulate_state case 0xce: /* into */ case 0xd4: /* aam */ case 0xd5: /* aad */ - case 0xd6: /* salc */ + /* 0xd6 (salc) omitted here, for #UD to be raised in 64-bit mode. */ s->not_64bit = true; break; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2470,9 +2470,17 @@ x86_emulate( _regs.eflags |= even_parity(_regs.al) ? X86_EFLAGS_PF : 0; break; - case 0xd6: /* salc */ - _regs.al = (_regs.eflags & X86_EFLAGS_CF) ? 0xff : 0x00; - break; + case 0xd6: /* salc / udb */ + if ( !mode_64bit() ) + { + _regs.al = (_regs.eflags & X86_EFLAGS_CF) ? 0xff : 0x00; + break; + } + fallthrough; + case X86EMUL_OPC(0x0f, 0x0b): /* ud2 */ + case X86EMUL_OPC(0x0f, 0xb9): /* ud1 */ + case X86EMUL_OPC(0x0f, 0xff): /* ud0 */ + generate_exception(X86_EXC_UD); case 0xd7: /* xlat */ { unsigned long al; @@ -3204,11 +3212,6 @@ x86_emulate( goto done; break; - case X86EMUL_OPC(0x0f, 0x0b): /* ud2 */ - case X86EMUL_OPC(0x0f, 0xb9): /* ud1 */ - case X86EMUL_OPC(0x0f, 0xff): /* ud0 */ - generate_exception(X86_EXC_UD); - case X86EMUL_OPC(0x0f, 0x0d): /* GrpP (prefetch) */ case X86EMUL_OPC(0x0f, 0x18): /* Grp16 (prefetch/nop) */ case X86EMUL_OPC(0x0f, 0x19) ... X86EMUL_OPC(0x0f, 0x1f): /* nop */
