aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-07-17 07:20:30 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-20 13:16:29 -0400
commit35f3f28613bc7263949db23a4c7078e425810c8c (patch)
tree134729d56cf503029e1e667df9bfe30b7410ad3b
parent90cb0529dd230548a7f0d6b315997be854caea1b (diff)
KVM: x86 emulator: implement rdmsr and wrmsr
Allow real-mode emulation of rdmsr and wrmsr. This allows smp Windows to boot, presumably for its sipi trampoline. Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/kvm.h2
-rw-r--r--drivers/kvm/kvm_main.c8
-rw-r--r--drivers/kvm/x86_emulate.c26
3 files changed, 31 insertions, 5 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 6636ae2ee3b5..3ac9cbce3369 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -569,6 +569,8 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
569unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr); 569unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr);
570void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value, 570void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
571 unsigned long *rflags); 571 unsigned long *rflags);
572int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data);
573int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
572 574
573struct x86_emulate_ctxt; 575struct x86_emulate_ctxt;
574 576
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 05f0418f2195..bcbe6835beb4 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1517,7 +1517,7 @@ EXPORT_SYMBOL_GPL(kvm_get_msr_common);
1517 * Returns 0 on success, non-0 otherwise. 1517 * Returns 0 on success, non-0 otherwise.
1518 * Assumes vcpu_load() was already called. 1518 * Assumes vcpu_load() was already called.
1519 */ 1519 */
1520static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) 1520int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
1521{ 1521{
1522 return kvm_arch_ops->get_msr(vcpu, msr_index, pdata); 1522 return kvm_arch_ops->get_msr(vcpu, msr_index, pdata);
1523} 1523}
@@ -1595,7 +1595,7 @@ EXPORT_SYMBOL_GPL(kvm_set_msr_common);
1595 * Returns 0 on success, non-0 otherwise. 1595 * Returns 0 on success, non-0 otherwise.
1596 * Assumes vcpu_load() was already called. 1596 * Assumes vcpu_load() was already called.
1597 */ 1597 */
1598static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) 1598int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
1599{ 1599{
1600 return kvm_arch_ops->set_msr(vcpu, msr_index, data); 1600 return kvm_arch_ops->set_msr(vcpu, msr_index, data);
1601} 1601}
@@ -2133,7 +2133,7 @@ static __init void kvm_init_msr_list(void)
2133 */ 2133 */
2134static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) 2134static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
2135{ 2135{
2136 return set_msr(vcpu, index, *data); 2136 return kvm_set_msr(vcpu, index, *data);
2137} 2137}
2138 2138
2139/* 2139/*
@@ -2617,7 +2617,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
2617 break; 2617 break;
2618 } 2618 }
2619 case KVM_GET_MSRS: 2619 case KVM_GET_MSRS:
2620 r = msr_io(vcpu, argp, get_msr, 1); 2620 r = msr_io(vcpu, argp, kvm_get_msr, 1);
2621 break; 2621 break;
2622 case KVM_SET_MSRS: 2622 case KVM_SET_MSRS:
2623 r = msr_io(vcpu, argp, do_set_msr, 0); 2623 r = msr_io(vcpu, argp, do_set_msr, 0);
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index f60012d62610..1b800fc00342 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -163,7 +163,7 @@ static u16 twobyte_table[256] = {
163 ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0, 163 ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0, 0, 164 0, 0, 0, 0, 0, 0, 0, 0,
165 /* 0x30 - 0x3F */ 165 /* 0x30 - 0x3F */
166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166 ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167 /* 0x40 - 0x47 */ 167 /* 0x40 - 0x47 */
168 DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, 168 DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
169 DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, 169 DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -486,6 +486,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
486 unsigned long modrm_ea; 486 unsigned long modrm_ea;
487 int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0; 487 int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
488 int no_wb = 0; 488 int no_wb = 0;
489 u64 msr_data;
489 490
490 /* Shadow copy of register state. Committed on successful emulation. */ 491 /* Shadow copy of register state. Committed on successful emulation. */
491 unsigned long _regs[NR_VCPU_REGS]; 492 unsigned long _regs[NR_VCPU_REGS];
@@ -1344,6 +1345,29 @@ twobyte_special_insn:
1344 goto cannot_emulate; 1345 goto cannot_emulate;
1345 realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags); 1346 realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
1346 break; 1347 break;
1348 case 0x30:
1349 /* wrmsr */
1350 msr_data = (u32)_regs[VCPU_REGS_RAX]
1351 | ((u64)_regs[VCPU_REGS_RDX] << 32);
1352 rc = kvm_set_msr(ctxt->vcpu, _regs[VCPU_REGS_RCX], msr_data);
1353 if (rc) {
1354 kvm_arch_ops->inject_gp(ctxt->vcpu, 0);
1355 _eip = ctxt->vcpu->rip;
1356 }
1357 rc = X86EMUL_CONTINUE;
1358 break;
1359 case 0x32:
1360 /* rdmsr */
1361 rc = kvm_get_msr(ctxt->vcpu, _regs[VCPU_REGS_RCX], &msr_data);
1362 if (rc) {
1363 kvm_arch_ops->inject_gp(ctxt->vcpu, 0);
1364 _eip = ctxt->vcpu->rip;
1365 } else {
1366 _regs[VCPU_REGS_RAX] = (u32)msr_data;
1367 _regs[VCPU_REGS_RDX] = msr_data >> 32;
1368 }
1369 rc = X86EMUL_CONTINUE;
1370 break;
1347 case 0xc7: /* Grp9 (cmpxchg8b) */ 1371 case 0xc7: /* Grp9 (cmpxchg8b) */
1348 { 1372 {
1349 u64 old, new; 1373 u64 old, new;