diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2014-06-30 04:54:17 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-07-09 12:09:55 -0400 |
commit | 9bf418335e24da995ea682a028926d7e1036be6f (patch) | |
tree | 2744a9564a101286b60272ff7eff4c216326d19c | |
parent | 62baf44cad3bc6b37115cc21e4228fe53d4f3474 (diff) |
KVM: nSVM: Fix IOIO bitmap evaluation
First, kvm_read_guest returns 0 on success. And then we need to take the
access size into account when testing the bitmap: intercept if any of
bits corresponding to the access is set.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/svm.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c79766e1f1e0..3483ac978c76 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -2116,22 +2116,27 @@ static void nested_svm_unmap(struct page *page) | |||
2116 | 2116 | ||
2117 | static int nested_svm_intercept_ioio(struct vcpu_svm *svm) | 2117 | static int nested_svm_intercept_ioio(struct vcpu_svm *svm) |
2118 | { | 2118 | { |
2119 | unsigned port; | 2119 | unsigned port, size, iopm_len; |
2120 | u8 val, bit; | 2120 | u16 val, mask; |
2121 | u8 start_bit; | ||
2121 | u64 gpa; | 2122 | u64 gpa; |
2122 | 2123 | ||
2123 | if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT))) | 2124 | if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT))) |
2124 | return NESTED_EXIT_HOST; | 2125 | return NESTED_EXIT_HOST; |
2125 | 2126 | ||
2126 | port = svm->vmcb->control.exit_info_1 >> 16; | 2127 | port = svm->vmcb->control.exit_info_1 >> 16; |
2128 | size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >> | ||
2129 | SVM_IOIO_SIZE_SHIFT; | ||
2127 | gpa = svm->nested.vmcb_iopm + (port / 8); | 2130 | gpa = svm->nested.vmcb_iopm + (port / 8); |
2128 | bit = port % 8; | 2131 | start_bit = port % 8; |
2129 | val = 0; | 2132 | iopm_len = (start_bit + size > 8) ? 2 : 1; |
2133 | mask = (0xf >> (4 - size)) << start_bit; | ||
2134 | val = 0; | ||
2130 | 2135 | ||
2131 | if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, 1)) | 2136 | if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, iopm_len)) |
2132 | val &= (1 << bit); | 2137 | return NESTED_EXIT_DONE; |
2133 | 2138 | ||
2134 | return val ? NESTED_EXIT_DONE : NESTED_EXIT_HOST; | 2139 | return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST; |
2135 | } | 2140 | } |
2136 | 2141 | ||
2137 | static int nested_svm_exit_handled_msr(struct vcpu_svm *svm) | 2142 | static int nested_svm_exit_handled_msr(struct vcpu_svm *svm) |