aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-06-18 10:19:24 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-06-19 06:52:14 -0400
commita449c7aa51e10c9bde0ea9bee4e682d6d067ebab (patch)
tree3689ce719fd1bb431d1a250691b474ca2021a91a
parent5777392e83c96e3a0799dd2985598e0fc76cf4aa (diff)
KVM: x86: Hypercall handling does not considers opsize correctly
Currently, the hypercall handling routine only considers LME as an indication to whether the guest uses 32/64-bit mode. This is incosistent with hyperv hypercalls handling and against the common sense of considering cs.l as well. This patch uses is_64_bit_mode instead of is_long_mode for that matter. In addition, the result is masked in respect to the guest execution mode. Last, it changes kvm_hv_hypercall to use is_64_bit_mode as well to simplify the code. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/x86.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 451d6acea808..874607ae0583 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5669,7 +5669,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
5669 u64 param, ingpa, outgpa, ret; 5669 u64 param, ingpa, outgpa, ret;
5670 uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0; 5670 uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
5671 bool fast, longmode; 5671 bool fast, longmode;
5672 int cs_db, cs_l;
5673 5672
5674 /* 5673 /*
5675 * hypercall generates UD from non zero cpl and real mode 5674 * hypercall generates UD from non zero cpl and real mode
@@ -5680,8 +5679,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
5680 return 0; 5679 return 0;
5681 } 5680 }
5682 5681
5683 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); 5682 longmode = is_64_bit_mode(vcpu);
5684 longmode = is_long_mode(vcpu) && cs_l == 1;
5685 5683
5686 if (!longmode) { 5684 if (!longmode) {
5687 param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) | 5685 param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
@@ -5746,7 +5744,7 @@ static void kvm_pv_kick_cpu_op(struct kvm *kvm, unsigned long flags, int apicid)
5746int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) 5744int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
5747{ 5745{
5748 unsigned long nr, a0, a1, a2, a3, ret; 5746 unsigned long nr, a0, a1, a2, a3, ret;
5749 int r = 1; 5747 int op_64_bit, r = 1;
5750 5748
5751 if (kvm_hv_hypercall_enabled(vcpu->kvm)) 5749 if (kvm_hv_hypercall_enabled(vcpu->kvm))
5752 return kvm_hv_hypercall(vcpu); 5750 return kvm_hv_hypercall(vcpu);
@@ -5759,7 +5757,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
5759 5757
5760 trace_kvm_hypercall(nr, a0, a1, a2, a3); 5758 trace_kvm_hypercall(nr, a0, a1, a2, a3);
5761 5759
5762 if (!is_long_mode(vcpu)) { 5760 op_64_bit = is_64_bit_mode(vcpu);
5761 if (!op_64_bit) {
5763 nr &= 0xFFFFFFFF; 5762 nr &= 0xFFFFFFFF;
5764 a0 &= 0xFFFFFFFF; 5763 a0 &= 0xFFFFFFFF;
5765 a1 &= 0xFFFFFFFF; 5764 a1 &= 0xFFFFFFFF;
@@ -5785,6 +5784,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
5785 break; 5784 break;
5786 } 5785 }
5787out: 5786out:
5787 if (!op_64_bit)
5788 ret = (u32)ret;
5788 kvm_register_write(vcpu, VCPU_REGS_RAX, ret); 5789 kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
5789 ++vcpu->stat.hypercalls; 5790 ++vcpu->stat.hypercalls;
5790 return r; 5791 return r;