diff options
author | Bandan Das <bsd@redhat.com> | 2014-05-06 02:19:15 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-05-06 12:59:57 -0400 |
commit | 19677e32fe7d6913e07ce80f6f3dc7663ac7fe67 (patch) | |
tree | 28e68e063a8e84b22e58e1428fa49ec307834575 /arch/x86/kvm | |
parent | 2ce316f0b9b2103e27585180b6aa6f17f0175f0e (diff) |
KVM: nVMX: rearrange get_vmx_mem_address
Our common function for vmptr checks (in 2/4) needs to fetch
the memory address
Signed-off-by: Bandan Das <bsd@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/vmx.c | 106 |
1 files changed, 53 insertions, 53 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 72b8012991b9..917a15efc45b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -5792,6 +5792,59 @@ static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer) | |||
5792 | } | 5792 | } |
5793 | 5793 | ||
5794 | /* | 5794 | /* |
5795 | * Decode the memory-address operand of a vmx instruction, as recorded on an | ||
5796 | * exit caused by such an instruction (run by a guest hypervisor). | ||
5797 | * On success, returns 0. When the operand is invalid, returns 1 and throws | ||
5798 | * #UD or #GP. | ||
5799 | */ | ||
5800 | static int get_vmx_mem_address(struct kvm_vcpu *vcpu, | ||
5801 | unsigned long exit_qualification, | ||
5802 | u32 vmx_instruction_info, gva_t *ret) | ||
5803 | { | ||
5804 | /* | ||
5805 | * According to Vol. 3B, "Information for VM Exits Due to Instruction | ||
5806 | * Execution", on an exit, vmx_instruction_info holds most of the | ||
5807 | * addressing components of the operand. Only the displacement part | ||
5808 | * is put in exit_qualification (see 3B, "Basic VM-Exit Information"). | ||
5809 | * For how an actual address is calculated from all these components, | ||
5810 | * refer to Vol. 1, "Operand Addressing". | ||
5811 | */ | ||
5812 | int scaling = vmx_instruction_info & 3; | ||
5813 | int addr_size = (vmx_instruction_info >> 7) & 7; | ||
5814 | bool is_reg = vmx_instruction_info & (1u << 10); | ||
5815 | int seg_reg = (vmx_instruction_info >> 15) & 7; | ||
5816 | int index_reg = (vmx_instruction_info >> 18) & 0xf; | ||
5817 | bool index_is_valid = !(vmx_instruction_info & (1u << 22)); | ||
5818 | int base_reg = (vmx_instruction_info >> 23) & 0xf; | ||
5819 | bool base_is_valid = !(vmx_instruction_info & (1u << 27)); | ||
5820 | |||
5821 | if (is_reg) { | ||
5822 | kvm_queue_exception(vcpu, UD_VECTOR); | ||
5823 | return 1; | ||
5824 | } | ||
5825 | |||
5826 | /* Addr = segment_base + offset */ | ||
5827 | /* offset = base + [index * scale] + displacement */ | ||
5828 | *ret = vmx_get_segment_base(vcpu, seg_reg); | ||
5829 | if (base_is_valid) | ||
5830 | *ret += kvm_register_read(vcpu, base_reg); | ||
5831 | if (index_is_valid) | ||
5832 | *ret += kvm_register_read(vcpu, index_reg)<<scaling; | ||
5833 | *ret += exit_qualification; /* holds the displacement */ | ||
5834 | |||
5835 | if (addr_size == 1) /* 32 bit */ | ||
5836 | *ret &= 0xffffffff; | ||
5837 | |||
5838 | /* | ||
5839 | * TODO: throw #GP (and return 1) in various cases that the VM* | ||
5840 | * instructions require it - e.g., offset beyond segment limit, | ||
5841 | * unusable or unreadable/unwritable segment, non-canonical 64-bit | ||
5842 | * address, and so on. Currently these are not checked. | ||
5843 | */ | ||
5844 | return 0; | ||
5845 | } | ||
5846 | |||
5847 | /* | ||
5795 | * Emulate the VMXON instruction. | 5848 | * Emulate the VMXON instruction. |
5796 | * Currently, we just remember that VMX is active, and do not save or even | 5849 | * Currently, we just remember that VMX is active, and do not save or even |
5797 | * inspect the argument to VMXON (the so-called "VMXON pointer") because we | 5850 | * inspect the argument to VMXON (the so-called "VMXON pointer") because we |
@@ -5951,59 +6004,6 @@ static int handle_vmoff(struct kvm_vcpu *vcpu) | |||
5951 | return 1; | 6004 | return 1; |
5952 | } | 6005 | } |
5953 | 6006 | ||
5954 | /* | ||
5955 | * Decode the memory-address operand of a vmx instruction, as recorded on an | ||
5956 | * exit caused by such an instruction (run by a guest hypervisor). | ||
5957 | * On success, returns 0. When the operand is invalid, returns 1 and throws | ||
5958 | * #UD or #GP. | ||
5959 | */ | ||
5960 | static int get_vmx_mem_address(struct kvm_vcpu *vcpu, | ||
5961 | unsigned long exit_qualification, | ||
5962 | u32 vmx_instruction_info, gva_t *ret) | ||
5963 | { | ||
5964 | /* | ||
5965 | * According to Vol. 3B, "Information for VM Exits Due to Instruction | ||
5966 | * Execution", on an exit, vmx_instruction_info holds most of the | ||
5967 | * addressing components of the operand. Only the displacement part | ||
5968 | * is put in exit_qualification (see 3B, "Basic VM-Exit Information"). | ||
5969 | * For how an actual address is calculated from all these components, | ||
5970 | * refer to Vol. 1, "Operand Addressing". | ||
5971 | */ | ||
5972 | int scaling = vmx_instruction_info & 3; | ||
5973 | int addr_size = (vmx_instruction_info >> 7) & 7; | ||
5974 | bool is_reg = vmx_instruction_info & (1u << 10); | ||
5975 | int seg_reg = (vmx_instruction_info >> 15) & 7; | ||
5976 | int index_reg = (vmx_instruction_info >> 18) & 0xf; | ||
5977 | bool index_is_valid = !(vmx_instruction_info & (1u << 22)); | ||
5978 | int base_reg = (vmx_instruction_info >> 23) & 0xf; | ||
5979 | bool base_is_valid = !(vmx_instruction_info & (1u << 27)); | ||
5980 | |||
5981 | if (is_reg) { | ||
5982 | kvm_queue_exception(vcpu, UD_VECTOR); | ||
5983 | return 1; | ||
5984 | } | ||
5985 | |||
5986 | /* Addr = segment_base + offset */ | ||
5987 | /* offset = base + [index * scale] + displacement */ | ||
5988 | *ret = vmx_get_segment_base(vcpu, seg_reg); | ||
5989 | if (base_is_valid) | ||
5990 | *ret += kvm_register_read(vcpu, base_reg); | ||
5991 | if (index_is_valid) | ||
5992 | *ret += kvm_register_read(vcpu, index_reg)<<scaling; | ||
5993 | *ret += exit_qualification; /* holds the displacement */ | ||
5994 | |||
5995 | if (addr_size == 1) /* 32 bit */ | ||
5996 | *ret &= 0xffffffff; | ||
5997 | |||
5998 | /* | ||
5999 | * TODO: throw #GP (and return 1) in various cases that the VM* | ||
6000 | * instructions require it - e.g., offset beyond segment limit, | ||
6001 | * unusable or unreadable/unwritable segment, non-canonical 64-bit | ||
6002 | * address, and so on. Currently these are not checked. | ||
6003 | */ | ||
6004 | return 0; | ||
6005 | } | ||
6006 | |||
6007 | /* Emulate the VMCLEAR instruction */ | 6007 | /* Emulate the VMCLEAR instruction */ |
6008 | static int handle_vmclear(struct kvm_vcpu *vcpu) | 6008 | static int handle_vmclear(struct kvm_vcpu *vcpu) |
6009 | { | 6009 | { |