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/kvm/x86.c | |
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/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 114 |
1 files changed, 58 insertions, 56 deletions
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]; |