diff options
author | Avi Kivity <avi@qumranet.com> | 2007-07-17 07:20:30 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-07-20 13:16:29 -0400 |
commit | 35f3f28613bc7263949db23a4c7078e425810c8c (patch) | |
tree | 134729d56cf503029e1e667df9bfe30b7410ad3b | |
parent | 90cb0529dd230548a7f0d6b315997be854caea1b (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.h | 2 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 8 | ||||
-rw-r--r-- | drivers/kvm/x86_emulate.c | 26 |
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, | |||
569 | unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr); | 569 | unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr); |
570 | void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value, | 570 | void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value, |
571 | unsigned long *rflags); | 571 | unsigned long *rflags); |
572 | int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data); | ||
573 | int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); | ||
572 | 574 | ||
573 | struct x86_emulate_ctxt; | 575 | struct 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 | */ |
1520 | static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | 1520 | int 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 | */ |
1598 | static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | 1598 | int 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 | */ |
2134 | static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) | 2134 | static 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; |