Add asm_safe(), asm_safe_report(), and asm_safe_report_ex() macros to reduce the boilerplate needed for using ASM_TRY() with a single instruction. Convert the memory test to the report variants to showcase the usage. Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- lib/x86/desc.h | 26 ++++++++++++++++++++++ x86/memory.c | 60 ++++++++++++-------------------------------------- 2 files changed, 40 insertions(+), 46 deletions(-) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index c023b932..8079d462 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -272,4 +272,30 @@ extern gdt_entry_t *get_tss_descr(void); extern unsigned long get_gdt_entry_base(gdt_entry_t *entry); extern unsigned long get_gdt_entry_limit(gdt_entry_t *entry); +#define asm_safe(insn, inputs...) \ +({ \ + asm volatile(ASM_TRY("1f") \ + insn "\n\t" \ + "1:\n\t" \ + : \ + : inputs \ + : "memory"); \ + exception_vector(); \ +}) + +#define __asm_safe_report(want, insn, inputs...) \ +do { \ + int vector = asm_safe(insn, inputs); \ + \ + report(vector == want, "Expected %s on '%s', got %s", \ + want ? exception_mnemonic(want) : "SUCCESS", \ + insn, \ + vector ? exception_mnemonic(vector) : "SUCCESS"); \ +} while (0) + +#define asm_safe_report(insn, inputs...) \ + __asm_safe_report(0, insn, inputs) + +#define asm_safe_report_ex __asm_safe_report + #endif diff --git a/x86/memory.c b/x86/memory.c index 58ef835e..ebfeceae 100644 --- a/x86/memory.c +++ b/x86/memory.c @@ -14,76 +14,44 @@ #include "processor.h" static long target; -static volatile int ud; -static volatile int isize; - -static void handle_ud(struct ex_regs *regs) -{ - ud = 1; - regs->rip += isize; -} int main(int ac, char **av) { - handle_exception(UD_VECTOR, handle_ud); - - /* 3-byte instructions: */ - isize = 3; - - if (this_cpu_has(X86_FEATURE_CLFLUSH)) { /* CLFLUSH */ - ud = 0; - asm volatile("clflush (%0)" : : "b" (&target)); - report(!ud, "clflush"); - } else { + if (this_cpu_has(X86_FEATURE_CLFLUSH)) + asm_safe_report("clflush (%0)", "b" (&target)); + else report_skip("clflush"); - } - if (this_cpu_has(X86_FEATURE_XMM)) { /* SSE */ - ud = 0; - asm volatile("sfence"); - report(!ud, "sfence"); - } else { + if (this_cpu_has(X86_FEATURE_XMM)) + asm_safe_report("sfence"); + else report_skip("sfence"); - } - if (this_cpu_has(X86_FEATURE_XMM2)) { /* SSE2 */ - ud = 0; - asm volatile("lfence"); - report(!ud, "lfence"); - ud = 0; - asm volatile("mfence"); - report(!ud, "mfence"); + if (this_cpu_has(X86_FEATURE_XMM2)) { + asm_safe_report("lfence"); + asm_safe_report("mfence"); } else { report_skip("lfence"); report_skip("mfence"); } - /* 4-byte instructions: */ - isize = 4; - - if (this_cpu_has(X86_FEATURE_CLFLUSHOPT)) { /* CLFLUSHOPT */ - ud = 0; + if (this_cpu_has(X86_FEATURE_CLFLUSHOPT)) { /* clflushopt (%rbx): */ - asm volatile(".byte 0x66, 0x0f, 0xae, 0x3b" : : "b" (&target)); - report(!ud, "clflushopt"); + asm_safe_report(".byte 0x66, 0x0f, 0xae, 0x3b", "b" (&target)); } else { report_skip("clflushopt"); } - if (this_cpu_has(X86_FEATURE_CLWB)) { /* CLWB */ - ud = 0; + if (this_cpu_has(X86_FEATURE_CLWB)) { /* clwb (%rbx): */ - asm volatile(".byte 0x66, 0x0f, 0xae, 0x33" : : "b" (&target)); - report(!ud, "clwb"); + asm_safe_report(".byte 0x66, 0x0f, 0xae, 0x33", "b" (&target)); } else { report_skip("clwb"); } if (this_cpu_has(X86_FEATURE_PCOMMIT)) { /* PCOMMIT */ - ud = 0; /* pcommit: */ - asm volatile(".byte 0x66, 0x0f, 0xae, 0xf8"); - report(!ud, "pcommit"); + asm_safe_report(".byte 0x66, 0x0f, 0xae, 0xf8"); } else { report_skip("pcommit"); } -- 2.40.0.348.gf938b09366-goog