Commit 0cb6f1e4 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

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: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarSean Christopherson <seanjc@google.com>
Link: https://lkml.kernel.org/r/20250714103439.637049932@infradead.org
parent c17b750b
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -178,9 +178,9 @@ void int3_emulate_ret(struct pt_regs *regs)
}

static __always_inline
void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp)
bool __emulate_cc(unsigned long flags, u8 cc)
{
	static const unsigned long jcc_mask[6] = {
	static const unsigned long cc_mask[6] = {
		[0] = X86_EFLAGS_OF,
		[1] = X86_EFLAGS_CF,
		[2] = X86_EFLAGS_ZF,
@@ -193,15 +193,21 @@ void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned lo
	bool match;

	if (cc < 0xc) {
		match = regs->flags & jcc_mask[cc >> 1];
		match = flags & cc_mask[cc >> 1];
	} else {
		match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
			((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
		match = ((flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
			((flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
		if (cc >= 0xe)
			match = match || (regs->flags & X86_EFLAGS_ZF);
			match = match || (flags & X86_EFLAGS_ZF);
	}

	return (match && !invert) || (!match && invert);
}

	if ((match && !invert) || (!match && invert))
static __always_inline
void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp)
{
	if (__emulate_cc(regs->flags, cc))
		ip += disp;

	int3_emulate_jmp(regs, ip);
+2 −32
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <asm/debugreg.h>
#include <asm/nospec-branch.h>
#include <asm/ibt.h>
#include <asm/text-patching.h>

#include "x86.h"
#include "tss.h"
@@ -416,31 +417,6 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
	ON64(FOP3E(op##q, rax, rdx, cl)) \
	FOP_END

/* Special case for SETcc - 1 instruction per cc */
#define FOP_SETCC(op) \
	FOP_FUNC(op) \
	#op " %al \n\t" \
	FOP_RET(op)

FOP_START(setcc)
FOP_SETCC(seto)
FOP_SETCC(setno)
FOP_SETCC(setc)
FOP_SETCC(setnc)
FOP_SETCC(setz)
FOP_SETCC(setnz)
FOP_SETCC(setbe)
FOP_SETCC(setnbe)
FOP_SETCC(sets)
FOP_SETCC(setns)
FOP_SETCC(setp)
FOP_SETCC(setnp)
FOP_SETCC(setl)
FOP_SETCC(setnl)
FOP_SETCC(setle)
FOP_SETCC(setnle)
FOP_END;

FOP_START(salc)
FOP_FUNC(salc)
"pushf; sbb %al, %al; popf \n\t"
@@ -1068,13 +1044,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)

static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
{
	u8 rc;
	void (*fop)(void) = (void *)em_setcc + FASTOP_SIZE * (condition & 0xf);

	flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
	asm("push %[flags]; popf; " CALL_NOSPEC
	    : "=a"(rc), ASM_CALL_CONSTRAINT : [thunk_target]"r"(fop), [flags]"r"(flags));
	return rc;
	return __emulate_cc(flags, condition & 0xf);
}

static void fetch_register_operand(struct operand *op)