diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2009-05-12 17:55:45 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-06-10 04:48:55 -0400 |
commit | 8986ecc0ef58c96eec48d8502c048f3ab67fd8e2 (patch) | |
tree | b2682f02bcb1e437e62463a17d7adc95a6735b60 | |
parent | b43b1901ad282aeb74161837fb403927102687a1 (diff) |
KVM: x86: check for cr3 validity in mmu_alloc_roots
Verify the cr3 address stored in vcpu->arch.cr3 points to an existant
memslot. If not, inject a triple fault.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/x86/kvm/mmu.c | 27 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 1 |
2 files changed, 24 insertions, 4 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 3ce60ad1fe37..5c3d6e81a7dc 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -1912,7 +1912,19 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu) | |||
1912 | vcpu->arch.mmu.root_hpa = INVALID_PAGE; | 1912 | vcpu->arch.mmu.root_hpa = INVALID_PAGE; |
1913 | } | 1913 | } |
1914 | 1914 | ||
1915 | static void mmu_alloc_roots(struct kvm_vcpu *vcpu) | 1915 | static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn) |
1916 | { | ||
1917 | int ret = 0; | ||
1918 | |||
1919 | if (!kvm_is_visible_gfn(vcpu->kvm, root_gfn)) { | ||
1920 | set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests); | ||
1921 | ret = 1; | ||
1922 | } | ||
1923 | |||
1924 | return ret; | ||
1925 | } | ||
1926 | |||
1927 | static int mmu_alloc_roots(struct kvm_vcpu *vcpu) | ||
1916 | { | 1928 | { |
1917 | int i; | 1929 | int i; |
1918 | gfn_t root_gfn; | 1930 | gfn_t root_gfn; |
@@ -1927,13 +1939,15 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) | |||
1927 | ASSERT(!VALID_PAGE(root)); | 1939 | ASSERT(!VALID_PAGE(root)); |
1928 | if (tdp_enabled) | 1940 | if (tdp_enabled) |
1929 | direct = 1; | 1941 | direct = 1; |
1942 | if (mmu_check_root(vcpu, root_gfn)) | ||
1943 | return 1; | ||
1930 | sp = kvm_mmu_get_page(vcpu, root_gfn, 0, | 1944 | sp = kvm_mmu_get_page(vcpu, root_gfn, 0, |
1931 | PT64_ROOT_LEVEL, direct, | 1945 | PT64_ROOT_LEVEL, direct, |
1932 | ACC_ALL, NULL); | 1946 | ACC_ALL, NULL); |
1933 | root = __pa(sp->spt); | 1947 | root = __pa(sp->spt); |
1934 | ++sp->root_count; | 1948 | ++sp->root_count; |
1935 | vcpu->arch.mmu.root_hpa = root; | 1949 | vcpu->arch.mmu.root_hpa = root; |
1936 | return; | 1950 | return 0; |
1937 | } | 1951 | } |
1938 | direct = !is_paging(vcpu); | 1952 | direct = !is_paging(vcpu); |
1939 | if (tdp_enabled) | 1953 | if (tdp_enabled) |
@@ -1950,6 +1964,8 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) | |||
1950 | root_gfn = vcpu->arch.pdptrs[i] >> PAGE_SHIFT; | 1964 | root_gfn = vcpu->arch.pdptrs[i] >> PAGE_SHIFT; |
1951 | } else if (vcpu->arch.mmu.root_level == 0) | 1965 | } else if (vcpu->arch.mmu.root_level == 0) |
1952 | root_gfn = 0; | 1966 | root_gfn = 0; |
1967 | if (mmu_check_root(vcpu, root_gfn)) | ||
1968 | return 1; | ||
1953 | sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, | 1969 | sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, |
1954 | PT32_ROOT_LEVEL, direct, | 1970 | PT32_ROOT_LEVEL, direct, |
1955 | ACC_ALL, NULL); | 1971 | ACC_ALL, NULL); |
@@ -1958,6 +1974,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) | |||
1958 | vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK; | 1974 | vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK; |
1959 | } | 1975 | } |
1960 | vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); | 1976 | vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); |
1977 | return 0; | ||
1961 | } | 1978 | } |
1962 | 1979 | ||
1963 | static void mmu_sync_roots(struct kvm_vcpu *vcpu) | 1980 | static void mmu_sync_roots(struct kvm_vcpu *vcpu) |
@@ -1976,7 +1993,7 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu) | |||
1976 | for (i = 0; i < 4; ++i) { | 1993 | for (i = 0; i < 4; ++i) { |
1977 | hpa_t root = vcpu->arch.mmu.pae_root[i]; | 1994 | hpa_t root = vcpu->arch.mmu.pae_root[i]; |
1978 | 1995 | ||
1979 | if (root) { | 1996 | if (root && VALID_PAGE(root)) { |
1980 | root &= PT64_BASE_ADDR_MASK; | 1997 | root &= PT64_BASE_ADDR_MASK; |
1981 | sp = page_header(root); | 1998 | sp = page_header(root); |
1982 | mmu_sync_children(vcpu, sp); | 1999 | mmu_sync_children(vcpu, sp); |
@@ -2311,9 +2328,11 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu) | |||
2311 | goto out; | 2328 | goto out; |
2312 | spin_lock(&vcpu->kvm->mmu_lock); | 2329 | spin_lock(&vcpu->kvm->mmu_lock); |
2313 | kvm_mmu_free_some_pages(vcpu); | 2330 | kvm_mmu_free_some_pages(vcpu); |
2314 | mmu_alloc_roots(vcpu); | 2331 | r = mmu_alloc_roots(vcpu); |
2315 | mmu_sync_roots(vcpu); | 2332 | mmu_sync_roots(vcpu); |
2316 | spin_unlock(&vcpu->kvm->mmu_lock); | 2333 | spin_unlock(&vcpu->kvm->mmu_lock); |
2334 | if (r) | ||
2335 | goto out; | ||
2317 | kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa); | 2336 | kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa); |
2318 | kvm_mmu_flush_tlb(vcpu); | 2337 | kvm_mmu_flush_tlb(vcpu); |
2319 | out: | 2338 | out: |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d2a4eca26181..3244437e67b3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4568,6 +4568,7 @@ int kvm_arch_set_memory_region(struct kvm *kvm, | |||
4568 | void kvm_arch_flush_shadow(struct kvm *kvm) | 4568 | void kvm_arch_flush_shadow(struct kvm *kvm) |
4569 | { | 4569 | { |
4570 | kvm_mmu_zap_all(kvm); | 4570 | kvm_mmu_zap_all(kvm); |
4571 | kvm_reload_remote_mmus(kvm); | ||
4571 | } | 4572 | } |
4572 | 4573 | ||
4573 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) | 4574 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) |