From 687fdbfe64086020e60547bd14773da3762056c1 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 24 May 2007 11:17:33 +0300 Subject: KVM: x86 emulator: implement wbinvd Vista seems to trigger it. Signed-off-by: Avi Kivity --- drivers/kvm/x86_emulate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/kvm/x86_emulate.c') diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 7ade09086aa..6123c0292b2 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -152,7 +152,7 @@ static u8 opcode_table[256] = { static u16 twobyte_table[256] = { /* 0x00 - 0x0F */ 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, - 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, + 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, /* 0x10 - 0x1F */ 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2F */ @@ -1304,6 +1304,8 @@ twobyte_special_insn: /* Disable writeback. */ dst.orig_val = dst.val; switch (b) { + case 0x09: /* wbinvd */ + break; case 0x0d: /* GrpP (prefetch) */ case 0x18: /* Grp16 (prefetch/nop) */ break; -- cgit v1.2.3-70-g09d2 From 72d6e5a08a8ba2105b3f36e32285e8fbfbed1f71 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 5 Jun 2007 16:15:51 +0300 Subject: KVM: Emulate hlt on real mode for Intel This has two use cases: the bios can't boot from disk, and guest smp bootstrap. Signed-off-by: Avi Kivity --- drivers/kvm/kvm.h | 1 + drivers/kvm/vmx.c | 7 ++++++- drivers/kvm/x86_emulate.c | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/kvm/x86_emulate.c') diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index ac358b8d3de..d49b16cae27 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -347,6 +347,7 @@ struct kvm_vcpu { u32 ar; } tr, es, ds, fs, gs; } rmode; + int halt_request; /* real mode on Intel only */ int cpuid_nent; struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES]; diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 90abd3c58c6..a1f51b9d482 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -1608,8 +1608,13 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) if (vcpu->rmode.active && handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK, - error_code)) + error_code)) { + if (vcpu->halt_request) { + vcpu->halt_request = 0; + return kvm_emulate_halt(vcpu); + } return 1; + } if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == (INTR_TYPE_EXCEPTION | 1)) { kvm_run->exit_reason = KVM_EXIT_DEBUG; diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 6123c0292b2..a4a84817b27 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -143,7 +143,8 @@ static u8 opcode_table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 - 0xF7 */ 0, 0, 0, 0, - 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, + ImplicitOps, 0, + ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, /* 0xF8 - 0xFF */ 0, 0, 0, 0, 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM @@ -1149,6 +1150,9 @@ special_insn: case 0xae ... 0xaf: /* scas */ DPRINTF("Urk! I don't handle SCAS.\n"); goto cannot_emulate; + case 0xf4: /* hlt */ + ctxt->vcpu->halt_request = 1; + goto done; } goto writeback; -- cgit v1.2.3-70-g09d2 From 7f0aaee07b6afcf5a4ee8a1132447621d768076b Mon Sep 17 00:00:00 2001 From: Nitin A Kamble Date: Tue, 19 Jun 2007 11:16:04 +0300 Subject: KVM: Implement emulation of "pop reg" instruction (opcode 0x58-0x5f) For use in real mode. Signed-off-by: Nitin A Kamble Signed-off-by: Avi Kivity --- drivers/kvm/x86_emulate.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/kvm/x86_emulate.c') diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index a4a84817b27..46c38063a10 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -98,8 +98,11 @@ static u8 opcode_table[256] = { 0, 0, 0, 0, /* 0x40 - 0x4F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x50 - 0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x50 - 0x57 */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x58 - 0x5F */ + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x60 - 0x6F */ 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1153,6 +1156,16 @@ special_insn: case 0xf4: /* hlt */ ctxt->vcpu->halt_request = 1; goto done; + case 0x58 ... 0x5f: /* pop reg */ + dst.ptr = (unsigned long *)&_regs[b & 0x7]; + + if ((rc = ops->read_std(register_address(ctxt->ss_base, + _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt)) != 0) + goto done; + + register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes); + dst.orig_val = dst.val; /* Disable writeback. */ + break; } goto writeback; -- cgit v1.2.3-70-g09d2 From d9413cd757a7c96d97ddb46ab4e3e04760ae4c55 Mon Sep 17 00:00:00 2001 From: Nitin A Kamble Date: Tue, 19 Jun 2007 11:21:15 +0300 Subject: KVM: Implement emulation of instruction "ret" (opcode 0xc3) Signed-off-by: Nitin A Kamble Signed-off-by: Avi Kivity --- drivers/kvm/x86_emulate.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/kvm/x86_emulate.c') diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 46c38063a10..92620e48f06 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -131,9 +131,9 @@ static u8 opcode_table[256] = { /* 0xB0 - 0xBF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xC7 */ - ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0, - 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov, - DstMem | SrcImm | ModRM | Mov, + ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, + 0, ImplicitOps, 0, 0, + ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov, /* 0xC8 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xD7 */ @@ -1156,14 +1156,18 @@ special_insn: case 0xf4: /* hlt */ ctxt->vcpu->halt_request = 1; goto done; + case 0xc3: /* ret */ + dst.ptr = &_eip; + goto pop_instruction; case 0x58 ... 0x5f: /* pop reg */ dst.ptr = (unsigned long *)&_regs[b & 0x7]; +pop_instruction: if ((rc = ops->read_std(register_address(ctxt->ss_base, _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt)) != 0) goto done; - register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes); + register_address_increment(_regs[VCPU_REGS_RSP], op_bytes); dst.orig_val = dst.val; /* Disable writeback. */ break; } -- cgit v1.2.3-70-g09d2 From 02c03a326a5df825cc01de426f72e160db2b9538 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Tue, 19 Jun 2007 22:41:20 +0200 Subject: KVM: Fix x86 emulator writeback When the old value and new one are the same the emulator skips the write; this is undesirable when the destination is a MMIO area and the write shall be performed regardless of the previous value. This optimization breaks e.g. a Linux guest APIC compiled without X86_GOOD_APIC. Remove the check and perform the writeback stage in the emulation unless it's explicitly disabled (currently push and some 2 bytes instructions may disable the writeback). Signed-Off-By: Luca Tettamanti Signed-off-by: Avi Kivity --- drivers/kvm/x86_emulate.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/kvm/x86_emulate.c') diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 92620e48f06..f60012d6261 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -485,6 +485,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) int mode = ctxt->mode; unsigned long modrm_ea; int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0; + int no_wb = 0; /* Shadow copy of register state. Committed on successful emulation. */ unsigned long _regs[NR_VCPU_REGS]; @@ -1051,7 +1052,7 @@ done_prefixes: _regs[VCPU_REGS_RSP]), &dst.val, dst.bytes, ctxt)) != 0) goto done; - dst.val = dst.orig_val; /* skanky: disable writeback */ + no_wb = 1; break; default: goto cannot_emulate; @@ -1060,7 +1061,7 @@ done_prefixes: } writeback: - if ((d & Mov) || (dst.orig_val != dst.val)) { + if (!no_wb) { switch (dst.type) { case OP_REG: /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ @@ -1168,7 +1169,7 @@ pop_instruction: goto done; register_address_increment(_regs[VCPU_REGS_RSP], op_bytes); - dst.orig_val = dst.val; /* Disable writeback. */ + no_wb = 1; /* Disable writeback. */ break; } goto writeback; @@ -1323,7 +1324,7 @@ twobyte_insn: twobyte_special_insn: /* Disable writeback. */ - dst.orig_val = dst.val; + no_wb = 1; switch (b) { case 0x09: /* wbinvd */ break; -- cgit v1.2.3-70-g09d2