diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:03 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:15:54 -0400 |
commit | 52a4661737ecc918633f6b05c611a4af4b5eae5a (patch) | |
tree | 25bf976f23423db921b5edde6854f0dc8391eb1c /arch/x86 | |
parent | 6ce5a090a9a0ea4266a2cad058c69e2f27201e11 (diff) |
KVM: Provide callback to get/set control registers in emulator ops.
Use this callback instead of directly call kvm function. Also rename
realmode_(set|get)_cr to emulator_(set|get)_cr since function has nothing
to do with real mode.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 7 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 114 |
4 files changed, 63 insertions, 63 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 2666d7ac3229..0c5caa469eb8 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h | |||
@@ -108,7 +108,8 @@ struct x86_emulate_ops { | |||
108 | const void *new, | 108 | const void *new, |
109 | unsigned int bytes, | 109 | unsigned int bytes, |
110 | struct kvm_vcpu *vcpu); | 110 | struct kvm_vcpu *vcpu); |
111 | 111 | ulong (*get_cr)(int cr, struct kvm_vcpu *vcpu); | |
112 | void (*set_cr)(int cr, ulong val, struct kvm_vcpu *vcpu); | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | /* Type, address-of, and value of an instruction's operand. */ | 115 | /* Type, address-of, and value of an instruction's operand. */ |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 53f520259471..9d474c7ae261 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -586,8 +586,6 @@ void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); | |||
586 | void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, | 586 | void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, |
587 | unsigned long *rflags); | 587 | unsigned long *rflags); |
588 | 588 | ||
589 | unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr); | ||
590 | void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value); | ||
591 | void kvm_enable_efer_bits(u64); | 589 | void kvm_enable_efer_bits(u64); |
592 | int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data); | 590 | int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data); |
593 | int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); | 591 | int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); |
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 91450b5cd49e..5b060e4be0e3 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2483,7 +2483,7 @@ twobyte_insn: | |||
2483 | break; | 2483 | break; |
2484 | case 4: /* smsw */ | 2484 | case 4: /* smsw */ |
2485 | c->dst.bytes = 2; | 2485 | c->dst.bytes = 2; |
2486 | c->dst.val = realmode_get_cr(ctxt->vcpu, 0); | 2486 | c->dst.val = ops->get_cr(0, ctxt->vcpu); |
2487 | break; | 2487 | break; |
2488 | case 6: /* lmsw */ | 2488 | case 6: /* lmsw */ |
2489 | realmode_lmsw(ctxt->vcpu, (u16)c->src.val, | 2489 | realmode_lmsw(ctxt->vcpu, (u16)c->src.val, |
@@ -2519,8 +2519,7 @@ twobyte_insn: | |||
2519 | case 0x20: /* mov cr, reg */ | 2519 | case 0x20: /* mov cr, reg */ |
2520 | if (c->modrm_mod != 3) | 2520 | if (c->modrm_mod != 3) |
2521 | goto cannot_emulate; | 2521 | goto cannot_emulate; |
2522 | c->regs[c->modrm_rm] = | 2522 | c->regs[c->modrm_rm] = ops->get_cr(c->modrm_reg, ctxt->vcpu); |
2523 | realmode_get_cr(ctxt->vcpu, c->modrm_reg); | ||
2524 | c->dst.type = OP_NONE; /* no writeback */ | 2523 | c->dst.type = OP_NONE; /* no writeback */ |
2525 | break; | 2524 | break; |
2526 | case 0x21: /* mov from dr to reg */ | 2525 | case 0x21: /* mov from dr to reg */ |
@@ -2534,7 +2533,7 @@ twobyte_insn: | |||
2534 | case 0x22: /* mov reg, cr */ | 2533 | case 0x22: /* mov reg, cr */ |
2535 | if (c->modrm_mod != 3) | 2534 | if (c->modrm_mod != 3) |
2536 | goto cannot_emulate; | 2535 | goto cannot_emulate; |
2537 | realmode_set_cr(ctxt->vcpu, c->modrm_reg, c->modrm_val); | 2536 | ops->set_cr(c->modrm_reg, c->modrm_val, ctxt->vcpu); |
2538 | c->dst.type = OP_NONE; | 2537 | c->dst.type = OP_NONE; |
2539 | break; | 2538 | break; |
2540 | case 0x23: /* mov from reg to dr */ | 2539 | case 0x23: /* mov from reg to dr */ |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 35db4f0db4ea..94a29759ab2c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -3423,12 +3423,70 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) | |||
3423 | } | 3423 | } |
3424 | EXPORT_SYMBOL_GPL(kvm_report_emulation_failure); | 3424 | EXPORT_SYMBOL_GPL(kvm_report_emulation_failure); |
3425 | 3425 | ||
3426 | static u64 mk_cr_64(u64 curr_cr, u32 new_val) | ||
3427 | { | ||
3428 | return (curr_cr & ~((1ULL << 32) - 1)) | new_val; | ||
3429 | } | ||
3430 | |||
3431 | static unsigned long emulator_get_cr(int cr, struct kvm_vcpu *vcpu) | ||
3432 | { | ||
3433 | unsigned long value; | ||
3434 | |||
3435 | switch (cr) { | ||
3436 | case 0: | ||
3437 | value = kvm_read_cr0(vcpu); | ||
3438 | break; | ||
3439 | case 2: | ||
3440 | value = vcpu->arch.cr2; | ||
3441 | break; | ||
3442 | case 3: | ||
3443 | value = vcpu->arch.cr3; | ||
3444 | break; | ||
3445 | case 4: | ||
3446 | value = kvm_read_cr4(vcpu); | ||
3447 | break; | ||
3448 | case 8: | ||
3449 | value = kvm_get_cr8(vcpu); | ||
3450 | break; | ||
3451 | default: | ||
3452 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); | ||
3453 | return 0; | ||
3454 | } | ||
3455 | |||
3456 | return value; | ||
3457 | } | ||
3458 | |||
3459 | static void emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu) | ||
3460 | { | ||
3461 | switch (cr) { | ||
3462 | case 0: | ||
3463 | kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val)); | ||
3464 | break; | ||
3465 | case 2: | ||
3466 | vcpu->arch.cr2 = val; | ||
3467 | break; | ||
3468 | case 3: | ||
3469 | kvm_set_cr3(vcpu, val); | ||
3470 | break; | ||
3471 | case 4: | ||
3472 | kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val)); | ||
3473 | break; | ||
3474 | case 8: | ||
3475 | kvm_set_cr8(vcpu, val & 0xfUL); | ||
3476 | break; | ||
3477 | default: | ||
3478 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); | ||
3479 | } | ||
3480 | } | ||
3481 | |||
3426 | static struct x86_emulate_ops emulate_ops = { | 3482 | static struct x86_emulate_ops emulate_ops = { |
3427 | .read_std = kvm_read_guest_virt_system, | 3483 | .read_std = kvm_read_guest_virt_system, |
3428 | .fetch = kvm_fetch_guest_virt, | 3484 | .fetch = kvm_fetch_guest_virt, |
3429 | .read_emulated = emulator_read_emulated, | 3485 | .read_emulated = emulator_read_emulated, |
3430 | .write_emulated = emulator_write_emulated, | 3486 | .write_emulated = emulator_write_emulated, |
3431 | .cmpxchg_emulated = emulator_cmpxchg_emulated, | 3487 | .cmpxchg_emulated = emulator_cmpxchg_emulated, |
3488 | .get_cr = emulator_get_cr, | ||
3489 | .set_cr = emulator_set_cr, | ||
3432 | }; | 3490 | }; |
3433 | 3491 | ||
3434 | static void cache_all_regs(struct kvm_vcpu *vcpu) | 3492 | static void cache_all_regs(struct kvm_vcpu *vcpu) |
@@ -4026,11 +4084,6 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu) | |||
4026 | return __emulator_write_emulated(rip, instruction, 3, vcpu, false); | 4084 | return __emulator_write_emulated(rip, instruction, 3, vcpu, false); |
4027 | } | 4085 | } |
4028 | 4086 | ||
4029 | static u64 mk_cr_64(u64 curr_cr, u32 new_val) | ||
4030 | { | ||
4031 | return (curr_cr & ~((1ULL << 32) - 1)) | new_val; | ||
4032 | } | ||
4033 | |||
4034 | void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base) | 4087 | void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base) |
4035 | { | 4088 | { |
4036 | struct desc_ptr dt = { limit, base }; | 4089 | struct desc_ptr dt = { limit, base }; |
@@ -4052,57 +4105,6 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, | |||
4052 | *rflags = kvm_get_rflags(vcpu); | 4105 | *rflags = kvm_get_rflags(vcpu); |
4053 | } | 4106 | } |
4054 | 4107 | ||
4055 | unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr) | ||
4056 | { | ||
4057 | unsigned long value; | ||
4058 | |||
4059 | switch (cr) { | ||
4060 | case 0: | ||
4061 | value = kvm_read_cr0(vcpu); | ||
4062 | break; | ||
4063 | case 2: | ||
4064 | value = vcpu->arch.cr2; | ||
4065 | break; | ||
4066 | case 3: | ||
4067 | value = vcpu->arch.cr3; | ||
4068 | break; | ||
4069 | case 4: | ||
4070 | value = kvm_read_cr4(vcpu); | ||
4071 | break; | ||
4072 | case 8: | ||
4073 | value = kvm_get_cr8(vcpu); | ||
4074 | break; | ||
4075 | default: | ||
4076 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); | ||
4077 | return 0; | ||
4078 | } | ||
4079 | |||
4080 | return value; | ||
4081 | } | ||
4082 | |||
4083 | void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val) | ||
4084 | { | ||
4085 | switch (cr) { | ||
4086 | case 0: | ||
4087 | kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val)); | ||
4088 | break; | ||
4089 | case 2: | ||
4090 | vcpu->arch.cr2 = val; | ||
4091 | break; | ||
4092 | case 3: | ||
4093 | kvm_set_cr3(vcpu, val); | ||
4094 | break; | ||
4095 | case 4: | ||
4096 | kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val)); | ||
4097 | break; | ||
4098 | case 8: | ||
4099 | kvm_set_cr8(vcpu, val & 0xfUL); | ||
4100 | break; | ||
4101 | default: | ||
4102 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr); | ||
4103 | } | ||
4104 | } | ||
4105 | |||
4106 | static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i) | 4108 | static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i) |
4107 | { | 4109 | { |
4108 | struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i]; | 4110 | struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i]; |