aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2010-03-01 09:34:39 -0500
committerAvi Kivity <avi@redhat.com>2010-05-17 05:15:15 -0400
commitce2ac085ff1500aad157cabd8221b7c38eb751bd (patch)
tree1058629ddd4dcdfe268b007d3c83bde8423e83a3 /arch
parent0d6b35378e80c555e20ca3aa3d3cc609b403cbb6 (diff)
KVM; SVM: Add correct handling of nested iopm
This patch adds the correct handling of the nested io permission bitmap. Old behavior was to not lookup the port in the iopm but only reinject an io intercept to the guest. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/svm.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 7cb2eb906eca..ddea391e78cd 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -79,6 +79,7 @@ struct nested_state {
79 79
80 /* gpa pointers to the real vectors */ 80 /* gpa pointers to the real vectors */
81 u64 vmcb_msrpm; 81 u64 vmcb_msrpm;
82 u64 vmcb_iopm;
82 83
83 /* A VMEXIT is required but not yet emulated */ 84 /* A VMEXIT is required but not yet emulated */
84 bool exit_required; 85 bool exit_required;
@@ -1658,6 +1659,26 @@ static void nested_svm_unmap(struct page *page)
1658 kvm_release_page_dirty(page); 1659 kvm_release_page_dirty(page);
1659} 1660}
1660 1661
1662static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
1663{
1664 unsigned port;
1665 u8 val, bit;
1666 u64 gpa;
1667
1668 if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT)))
1669 return NESTED_EXIT_HOST;
1670
1671 port = svm->vmcb->control.exit_info_1 >> 16;
1672 gpa = svm->nested.vmcb_iopm + (port / 8);
1673 bit = port % 8;
1674 val = 0;
1675
1676 if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, 1))
1677 val &= (1 << bit);
1678
1679 return val ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
1680}
1681
1661static int nested_svm_exit_handled_msr(struct vcpu_svm *svm) 1682static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
1662{ 1683{
1663 u32 offset, msr, value; 1684 u32 offset, msr, value;
@@ -1723,6 +1744,9 @@ static int nested_svm_intercept(struct vcpu_svm *svm)
1723 case SVM_EXIT_MSR: 1744 case SVM_EXIT_MSR:
1724 vmexit = nested_svm_exit_handled_msr(svm); 1745 vmexit = nested_svm_exit_handled_msr(svm);
1725 break; 1746 break;
1747 case SVM_EXIT_IOIO:
1748 vmexit = nested_svm_intercept_ioio(svm);
1749 break;
1726 case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: { 1750 case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: {
1727 u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0); 1751 u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0);
1728 if (svm->nested.intercept_cr_read & cr_bits) 1752 if (svm->nested.intercept_cr_read & cr_bits)
@@ -2047,6 +2071,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
2047 svm->vmcb->save.cpl = nested_vmcb->save.cpl; 2071 svm->vmcb->save.cpl = nested_vmcb->save.cpl;
2048 2072
2049 svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa; 2073 svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa;
2074 svm->nested.vmcb_iopm = nested_vmcb->control.iopm_base_pa & ~0x0fffULL;
2050 2075
2051 /* cache intercepts */ 2076 /* cache intercepts */
2052 svm->nested.intercept_cr_read = nested_vmcb->control.intercept_cr_read; 2077 svm->nested.intercept_cr_read = nested_vmcb->control.intercept_cr_read;