Commit 02d4160f authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Paolo Bonzini
Browse files

x86: KVM: add xsetbv to the emulator



To avoid hardcoding xsetbv length to '3' we need to support decoding it in
the emulator.

Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 97413d29
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ struct x86_emulate_ops {
	int (*pre_leave_smm)(struct x86_emulate_ctxt *ctxt,
			     const char *smstate);
	void (*post_leave_smm)(struct x86_emulate_ctxt *ctxt);

	int (*set_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr);
};

typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -429,6 +429,7 @@ enum x86_intercept {
	x86_intercept_ins,
	x86_intercept_out,
	x86_intercept_outs,
	x86_intercept_xsetbv,

	nr_x86_intercepts
};
+22 −1
Original line number Diff line number Diff line
@@ -4156,6 +4156,20 @@ out:
	return rc;
}

static int em_xsetbv(struct x86_emulate_ctxt *ctxt)
{
	u32 eax, ecx, edx;

	eax = reg_read(ctxt, VCPU_REGS_RAX);
	edx = reg_read(ctxt, VCPU_REGS_RDX);
	ecx = reg_read(ctxt, VCPU_REGS_RCX);

	if (ctxt->ops->set_xcr(ctxt, ecx, ((u64)edx << 32) | eax))
		return emulate_gp(ctxt, 0);

	return X86EMUL_CONTINUE;
}

static bool valid_cr(int nr)
{
	switch (nr) {
@@ -4409,6 +4423,12 @@ static const struct opcode group7_rm1[] = {
	N, N, N, N, N, N,
};

static const struct opcode group7_rm2[] = {
	N,
	II(ImplicitOps | Priv,			em_xsetbv,	xsetbv),
	N, N, N, N, N, N,
};

static const struct opcode group7_rm3[] = {
	DIP(SrcNone | Prot | Priv,		vmrun,		check_svme_pa),
	II(SrcNone  | Prot | EmulateOnUD,	em_hypercall,	vmmcall),
@@ -4498,7 +4518,8 @@ static const struct group_dual group7 = { {
}, {
	EXT(0, group7_rm0),
	EXT(0, group7_rm1),
	N, EXT(0, group7_rm3),
	EXT(0, group7_rm2),
	EXT(0, group7_rm3),
	II(SrcNone | DstMem | Mov,		em_smsw, smsw), N,
	II(SrcMem16 | Mov | Priv,		em_lmsw, lmsw),
	EXT(0, group7_rm7),
+1 −0
Original line number Diff line number Diff line
@@ -6076,6 +6076,7 @@ static const struct __x86_intercept {
	[x86_intercept_ins]		= POST_EX(SVM_EXIT_IOIO),
	[x86_intercept_out]		= POST_EX(SVM_EXIT_IOIO),
	[x86_intercept_outs]		= POST_EX(SVM_EXIT_IOIO),
	[x86_intercept_xsetbv]		= PRE_EX(SVM_EXIT_XSETBV),
};

#undef PRE_EX
+6 −0
Original line number Diff line number Diff line
@@ -6075,6 +6075,11 @@ static void emulator_post_leave_smm(struct x86_emulate_ctxt *ctxt)
	kvm_smm_changed(emul_to_vcpu(ctxt));
}

static int emulator_set_xcr(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr)
{
	return __kvm_set_xcr(emul_to_vcpu(ctxt), index, xcr);
}

static const struct x86_emulate_ops emulate_ops = {
	.read_gpr            = emulator_read_gpr,
	.write_gpr           = emulator_write_gpr,
@@ -6116,6 +6121,7 @@ static const struct x86_emulate_ops emulate_ops = {
	.set_hflags          = emulator_set_hflags,
	.pre_leave_smm       = emulator_pre_leave_smm,
	.post_leave_smm      = emulator_post_leave_smm,
	.set_xcr             = emulator_set_xcr,
};

static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)