aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c19
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
2117static int nested_svm_intercept_ioio(struct vcpu_svm *svm) 2117static 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
2137static int nested_svm_exit_handled_msr(struct vcpu_svm *svm) 2142static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)