diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-04-28 12:15:32 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:35:32 -0400 |
commit | 338dbc9781eb5acd0b12809d95d4006135f29767 (patch) | |
tree | ceb9fc9b2eb7e52c9352f094436590c82852d71f /arch | |
parent | 0f12244fe70e8a94a491f6cd7ed70a352ab6c26c (diff) |
KVM: x86 emulator: make (get|set)_dr() callback return error if it fails
Make (get|set)_dr() callback return error if it fails instead of
injecting exception behind emulator's back.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 11 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 63 |
2 files changed, 45 insertions, 29 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 061f7d37c9f7..d5979ecc2521 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -3151,9 +3151,14 @@ twobyte_insn: | |||
3151 | goto done; | 3151 | goto done; |
3152 | } | 3152 | } |
3153 | 3153 | ||
3154 | ops->set_dr(c->modrm_reg,c->regs[c->modrm_rm] & | 3154 | if (ops->set_dr(c->modrm_reg, c->regs[c->modrm_rm] & |
3155 | ((ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U), | 3155 | ((ctxt->mode == X86EMUL_MODE_PROT64) ? |
3156 | ctxt->vcpu); | 3156 | ~0ULL : ~0U), ctxt->vcpu) < 0) { |
3157 | /* #UD condition is already handled by the code above */ | ||
3158 | kvm_inject_gp(ctxt->vcpu, 0); | ||
3159 | goto done; | ||
3160 | } | ||
3161 | |||
3157 | c->dst.type = OP_NONE; /* no writeback */ | 3162 | c->dst.type = OP_NONE; /* no writeback */ |
3158 | break; | 3163 | break; |
3159 | case 0x30: | 3164 | case 0x30: |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 64c6e7a31411..44a546b136fc 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -573,7 +573,7 @@ unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) | |||
573 | } | 573 | } |
574 | EXPORT_SYMBOL_GPL(kvm_get_cr8); | 574 | EXPORT_SYMBOL_GPL(kvm_get_cr8); |
575 | 575 | ||
576 | int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | 576 | static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) |
577 | { | 577 | { |
578 | switch (dr) { | 578 | switch (dr) { |
579 | case 0 ... 3: | 579 | case 0 ... 3: |
@@ -582,29 +582,21 @@ int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | |||
582 | vcpu->arch.eff_db[dr] = val; | 582 | vcpu->arch.eff_db[dr] = val; |
583 | break; | 583 | break; |
584 | case 4: | 584 | case 4: |
585 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) { | 585 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) |
586 | kvm_queue_exception(vcpu, UD_VECTOR); | 586 | return 1; /* #UD */ |
587 | return 1; | ||
588 | } | ||
589 | /* fall through */ | 587 | /* fall through */ |
590 | case 6: | 588 | case 6: |
591 | if (val & 0xffffffff00000000ULL) { | 589 | if (val & 0xffffffff00000000ULL) |
592 | kvm_inject_gp(vcpu, 0); | 590 | return -1; /* #GP */ |
593 | return 1; | ||
594 | } | ||
595 | vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1; | 591 | vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1; |
596 | break; | 592 | break; |
597 | case 5: | 593 | case 5: |
598 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) { | 594 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) |
599 | kvm_queue_exception(vcpu, UD_VECTOR); | 595 | return 1; /* #UD */ |
600 | return 1; | ||
601 | } | ||
602 | /* fall through */ | 596 | /* fall through */ |
603 | default: /* 7 */ | 597 | default: /* 7 */ |
604 | if (val & 0xffffffff00000000ULL) { | 598 | if (val & 0xffffffff00000000ULL) |
605 | kvm_inject_gp(vcpu, 0); | 599 | return -1; /* #GP */ |
606 | return 1; | ||
607 | } | ||
608 | vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; | 600 | vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; |
609 | if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { | 601 | if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { |
610 | kvm_x86_ops->set_dr7(vcpu, vcpu->arch.dr7); | 602 | kvm_x86_ops->set_dr7(vcpu, vcpu->arch.dr7); |
@@ -615,28 +607,37 @@ int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | |||
615 | 607 | ||
616 | return 0; | 608 | return 0; |
617 | } | 609 | } |
610 | |||
611 | int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | ||
612 | { | ||
613 | int res; | ||
614 | |||
615 | res = __kvm_set_dr(vcpu, dr, val); | ||
616 | if (res > 0) | ||
617 | kvm_queue_exception(vcpu, UD_VECTOR); | ||
618 | else if (res < 0) | ||
619 | kvm_inject_gp(vcpu, 0); | ||
620 | |||
621 | return res; | ||
622 | } | ||
618 | EXPORT_SYMBOL_GPL(kvm_set_dr); | 623 | EXPORT_SYMBOL_GPL(kvm_set_dr); |
619 | 624 | ||
620 | int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) | 625 | static int _kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) |
621 | { | 626 | { |
622 | switch (dr) { | 627 | switch (dr) { |
623 | case 0 ... 3: | 628 | case 0 ... 3: |
624 | *val = vcpu->arch.db[dr]; | 629 | *val = vcpu->arch.db[dr]; |
625 | break; | 630 | break; |
626 | case 4: | 631 | case 4: |
627 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) { | 632 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) |
628 | kvm_queue_exception(vcpu, UD_VECTOR); | ||
629 | return 1; | 633 | return 1; |
630 | } | ||
631 | /* fall through */ | 634 | /* fall through */ |
632 | case 6: | 635 | case 6: |
633 | *val = vcpu->arch.dr6; | 636 | *val = vcpu->arch.dr6; |
634 | break; | 637 | break; |
635 | case 5: | 638 | case 5: |
636 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) { | 639 | if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) |
637 | kvm_queue_exception(vcpu, UD_VECTOR); | ||
638 | return 1; | 640 | return 1; |
639 | } | ||
640 | /* fall through */ | 641 | /* fall through */ |
641 | default: /* 7 */ | 642 | default: /* 7 */ |
642 | *val = vcpu->arch.dr7; | 643 | *val = vcpu->arch.dr7; |
@@ -645,6 +646,15 @@ int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) | |||
645 | 646 | ||
646 | return 0; | 647 | return 0; |
647 | } | 648 | } |
649 | |||
650 | int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) | ||
651 | { | ||
652 | if (_kvm_get_dr(vcpu, dr, val)) { | ||
653 | kvm_queue_exception(vcpu, UD_VECTOR); | ||
654 | return 1; | ||
655 | } | ||
656 | return 0; | ||
657 | } | ||
648 | EXPORT_SYMBOL_GPL(kvm_get_dr); | 658 | EXPORT_SYMBOL_GPL(kvm_get_dr); |
649 | 659 | ||
650 | static inline u32 bit(int bitno) | 660 | static inline u32 bit(int bitno) |
@@ -3619,12 +3629,13 @@ int emulate_clts(struct kvm_vcpu *vcpu) | |||
3619 | 3629 | ||
3620 | int emulator_get_dr(int dr, unsigned long *dest, struct kvm_vcpu *vcpu) | 3630 | int emulator_get_dr(int dr, unsigned long *dest, struct kvm_vcpu *vcpu) |
3621 | { | 3631 | { |
3622 | return kvm_get_dr(vcpu, dr, dest); | 3632 | return _kvm_get_dr(vcpu, dr, dest); |
3623 | } | 3633 | } |
3624 | 3634 | ||
3625 | int emulator_set_dr(int dr, unsigned long value, struct kvm_vcpu *vcpu) | 3635 | int emulator_set_dr(int dr, unsigned long value, struct kvm_vcpu *vcpu) |
3626 | { | 3636 | { |
3627 | return kvm_set_dr(vcpu, dr, value); | 3637 | |
3638 | return __kvm_set_dr(vcpu, dr, value); | ||
3628 | } | 3639 | } |
3629 | 3640 | ||
3630 | void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) | 3641 | void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) |