Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: Implement test_cc() in C

Current test_cc() uses the fastop infrastructure to test flags using
SETcc instructions. However, int3_emulate_jcc() already fully
implements the flags->CC mapping, use that.

Removes a pile of gnarly asm.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Sean Christopherson <seanjc@google.com>
Link: https://lkml.kernel.org/r/20250714103439.637049932@infradead.org

+15 -39
+13 -7
arch/x86/include/asm/text-patching.h
··· 178 178 } 179 179 180 180 static __always_inline 181 - void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp) 181 + bool __emulate_cc(unsigned long flags, u8 cc) 182 182 { 183 - static const unsigned long jcc_mask[6] = { 183 + static const unsigned long cc_mask[6] = { 184 184 [0] = X86_EFLAGS_OF, 185 185 [1] = X86_EFLAGS_CF, 186 186 [2] = X86_EFLAGS_ZF, ··· 193 193 bool match; 194 194 195 195 if (cc < 0xc) { 196 - match = regs->flags & jcc_mask[cc >> 1]; 196 + match = flags & cc_mask[cc >> 1]; 197 197 } else { 198 - match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^ 199 - ((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT); 198 + match = ((flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^ 199 + ((flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT); 200 200 if (cc >= 0xe) 201 - match = match || (regs->flags & X86_EFLAGS_ZF); 201 + match = match || (flags & X86_EFLAGS_ZF); 202 202 } 203 203 204 - if ((match && !invert) || (!match && invert)) 204 + return (match && !invert) || (!match && invert); 205 + } 206 + 207 + static __always_inline 208 + void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp) 209 + { 210 + if (__emulate_cc(regs->flags, cc)) 205 211 ip += disp; 206 212 207 213 int3_emulate_jmp(regs, ip);
+2 -32
arch/x86/kvm/emulate.c
··· 26 26 #include <asm/debugreg.h> 27 27 #include <asm/nospec-branch.h> 28 28 #include <asm/ibt.h> 29 + #include <asm/text-patching.h> 29 30 30 31 #include "x86.h" 31 32 #include "tss.h" ··· 416 415 FOP3E(op##l, eax, edx, cl) \ 417 416 ON64(FOP3E(op##q, rax, rdx, cl)) \ 418 417 FOP_END 419 - 420 - /* Special case for SETcc - 1 instruction per cc */ 421 - #define FOP_SETCC(op) \ 422 - FOP_FUNC(op) \ 423 - #op " %al \n\t" \ 424 - FOP_RET(op) 425 - 426 - FOP_START(setcc) 427 - FOP_SETCC(seto) 428 - FOP_SETCC(setno) 429 - FOP_SETCC(setc) 430 - FOP_SETCC(setnc) 431 - FOP_SETCC(setz) 432 - FOP_SETCC(setnz) 433 - FOP_SETCC(setbe) 434 - FOP_SETCC(setnbe) 435 - FOP_SETCC(sets) 436 - FOP_SETCC(setns) 437 - FOP_SETCC(setp) 438 - FOP_SETCC(setnp) 439 - FOP_SETCC(setl) 440 - FOP_SETCC(setnl) 441 - FOP_SETCC(setle) 442 - FOP_SETCC(setnle) 443 - FOP_END; 444 418 445 419 FOP_START(salc) 446 420 FOP_FUNC(salc) ··· 1044 1068 1045 1069 static __always_inline u8 test_cc(unsigned int condition, unsigned long flags) 1046 1070 { 1047 - u8 rc; 1048 - void (*fop)(void) = (void *)em_setcc + FASTOP_SIZE * (condition & 0xf); 1049 - 1050 - flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF; 1051 - asm("push %[flags]; popf; " CALL_NOSPEC 1052 - : "=a"(rc), ASM_CALL_CONSTRAINT : [thunk_target]"r"(fop), [flags]"r"(flags)); 1053 - return rc; 1071 + return __emulate_cc(flags, condition & 0xf); 1054 1072 } 1055 1073 1056 1074 static void fetch_register_operand(struct operand *op)