forked from Minki/linux
Merge tag 'kvm-3.10-2' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Gleb Natapov: "Most of the fixes are in the emulator since now we emulate more than we did before for correctness sake we see more bugs there, but there is also an OOPS fixed and corruption of xcr0 register." * tag 'kvm-3.10-2' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: emulator: emulate SALC KVM: emulator: emulate XLAT KVM: emulator: emulate AAM KVM: VMX: fix halt emulation while emulating invalid guest sate KVM: Fix kvm_irqfd_init initialization KVM: x86: fix maintenance of guest/host xcr0 state
This commit is contained in:
commit
c67723ebbb
@ -60,6 +60,7 @@
|
||||
#define OpGS 25ull /* GS */
|
||||
#define OpMem8 26ull /* 8-bit zero extended memory operand */
|
||||
#define OpImm64 27ull /* Sign extended 16/32/64-bit immediate */
|
||||
#define OpXLat 28ull /* memory at BX/EBX/RBX + zero-extended AL */
|
||||
|
||||
#define OpBits 5 /* Width of operand field */
|
||||
#define OpMask ((1ull << OpBits) - 1)
|
||||
@ -99,6 +100,7 @@
|
||||
#define SrcImmUByte (OpImmUByte << SrcShift)
|
||||
#define SrcImmU (OpImmU << SrcShift)
|
||||
#define SrcSI (OpSI << SrcShift)
|
||||
#define SrcXLat (OpXLat << SrcShift)
|
||||
#define SrcImmFAddr (OpImmFAddr << SrcShift)
|
||||
#define SrcMemFAddr (OpMemFAddr << SrcShift)
|
||||
#define SrcAcc (OpAcc << SrcShift)
|
||||
@ -533,6 +535,9 @@ FOP_SETCC(setle)
|
||||
FOP_SETCC(setnle)
|
||||
FOP_END;
|
||||
|
||||
FOP_START(salc) "pushf; sbb %al, %al; popf \n\t" FOP_RET
|
||||
FOP_END;
|
||||
|
||||
#define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \
|
||||
do { \
|
||||
unsigned long _tmp; \
|
||||
@ -2996,6 +3001,28 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int em_aam(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
u8 al, ah;
|
||||
|
||||
if (ctxt->src.val == 0)
|
||||
return emulate_de(ctxt);
|
||||
|
||||
al = ctxt->dst.val & 0xff;
|
||||
ah = al / ctxt->src.val;
|
||||
al %= ctxt->src.val;
|
||||
|
||||
ctxt->dst.val = (ctxt->dst.val & 0xffff0000) | al | (ah << 8);
|
||||
|
||||
/* Set PF, ZF, SF */
|
||||
ctxt->src.type = OP_IMM;
|
||||
ctxt->src.val = 0;
|
||||
ctxt->src.bytes = 1;
|
||||
fastop(ctxt, em_or);
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int em_aad(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
u8 al = ctxt->dst.val & 0xff;
|
||||
@ -3936,7 +3963,10 @@ static const struct opcode opcode_table[256] = {
|
||||
/* 0xD0 - 0xD7 */
|
||||
G(Src2One | ByteOp, group2), G(Src2One, group2),
|
||||
G(Src2CL | ByteOp, group2), G(Src2CL, group2),
|
||||
N, I(DstAcc | SrcImmByte | No64, em_aad), N, N,
|
||||
I(DstAcc | SrcImmUByte | No64, em_aam),
|
||||
I(DstAcc | SrcImmUByte | No64, em_aad),
|
||||
F(DstAcc | ByteOp | No64, em_salc),
|
||||
I(DstAcc | SrcXLat | ByteOp, em_mov),
|
||||
/* 0xD8 - 0xDF */
|
||||
N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N,
|
||||
/* 0xE0 - 0xE7 */
|
||||
@ -4198,6 +4228,16 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
|
||||
op->val = 0;
|
||||
op->count = 1;
|
||||
break;
|
||||
case OpXLat:
|
||||
op->type = OP_MEM;
|
||||
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
|
||||
op->addr.mem.ea =
|
||||
register_address(ctxt,
|
||||
reg_read(ctxt, VCPU_REGS_RBX) +
|
||||
(reg_read(ctxt, VCPU_REGS_RAX) & 0xff));
|
||||
op->addr.mem.seg = seg_override(ctxt);
|
||||
op->val = 0;
|
||||
break;
|
||||
case OpImmFAddr:
|
||||
op->type = OP_IMM;
|
||||
op->addr.mem.ea = ctxt->_eip;
|
||||
|
@ -5434,6 +5434,12 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vcpu->arch.halt_request) {
|
||||
vcpu->arch.halt_request = 0;
|
||||
ret = kvm_emulate_halt(vcpu);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (signal_pending(current))
|
||||
goto out;
|
||||
if (need_resched())
|
||||
|
@ -555,6 +555,25 @@ void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_lmsw);
|
||||
|
||||
static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) &&
|
||||
!vcpu->guest_xcr0_loaded) {
|
||||
/* kvm_set_xcr() also depends on this */
|
||||
xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
|
||||
vcpu->guest_xcr0_loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (vcpu->guest_xcr0_loaded) {
|
||||
if (vcpu->arch.xcr0 != host_xcr0)
|
||||
xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
|
||||
vcpu->guest_xcr0_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
|
||||
{
|
||||
u64 xcr0;
|
||||
@ -571,8 +590,8 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
|
||||
return 1;
|
||||
if (xcr0 & ~host_xcr0)
|
||||
return 1;
|
||||
kvm_put_guest_xcr0(vcpu);
|
||||
vcpu->arch.xcr0 = xcr0;
|
||||
vcpu->guest_xcr0_loaded = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5614,25 +5633,6 @@ static void inject_pending_event(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) &&
|
||||
!vcpu->guest_xcr0_loaded) {
|
||||
/* kvm_set_xcr() also depends on this */
|
||||
xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
|
||||
vcpu->guest_xcr0_loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (vcpu->guest_xcr0_loaded) {
|
||||
if (vcpu->arch.xcr0 != host_xcr0)
|
||||
xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
|
||||
vcpu->guest_xcr0_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_nmi(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned limit = 2;
|
||||
|
@ -3105,13 +3105,21 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
|
||||
int r;
|
||||
int cpu;
|
||||
|
||||
r = kvm_irqfd_init();
|
||||
if (r)
|
||||
goto out_irqfd;
|
||||
r = kvm_arch_init(opaque);
|
||||
if (r)
|
||||
goto out_fail;
|
||||
|
||||
/*
|
||||
* kvm_arch_init makes sure there's at most one caller
|
||||
* for architectures that support multiple implementations,
|
||||
* like intel and amd on x86.
|
||||
* kvm_arch_init must be called before kvm_irqfd_init to avoid creating
|
||||
* conflicts in case kvm is already setup for another implementation.
|
||||
*/
|
||||
r = kvm_irqfd_init();
|
||||
if (r)
|
||||
goto out_irqfd;
|
||||
|
||||
if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) {
|
||||
r = -ENOMEM;
|
||||
goto out_free_0;
|
||||
@ -3186,10 +3194,10 @@ out_free_1:
|
||||
out_free_0a:
|
||||
free_cpumask_var(cpus_hardware_enabled);
|
||||
out_free_0:
|
||||
kvm_arch_exit();
|
||||
out_fail:
|
||||
kvm_irqfd_exit();
|
||||
out_irqfd:
|
||||
kvm_arch_exit();
|
||||
out_fail:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_init);
|
||||
|
Loading…
Reference in New Issue
Block a user