aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r--arch/x86/kvm/mmu.c83
1 files changed, 29 insertions, 54 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c669f2af1d12..a25e1adb5cff 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1846,67 +1846,42 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
1846{ 1846{
1847} 1847}
1848 1848
1849struct direct_shadow_walk { 1849static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
1850 struct kvm_shadow_walk walker; 1850 int largepage, gfn_t gfn, pfn_t pfn)
1851 pfn_t pfn;
1852 int write;
1853 int largepage;
1854 int pt_write;
1855};
1856
1857static int direct_map_entry(struct kvm_shadow_walk *_walk,
1858 struct kvm_vcpu *vcpu,
1859 u64 addr, u64 *sptep, int level)
1860{ 1851{
1861 struct direct_shadow_walk *walk = 1852 struct kvm_shadow_walk_iterator iterator;
1862 container_of(_walk, struct direct_shadow_walk, walker);
1863 struct kvm_mmu_page *sp; 1853 struct kvm_mmu_page *sp;
1854 int pt_write = 0;
1864 gfn_t pseudo_gfn; 1855 gfn_t pseudo_gfn;
1865 gfn_t gfn = addr >> PAGE_SHIFT;
1866
1867 if (level == PT_PAGE_TABLE_LEVEL
1868 || (walk->largepage && level == PT_DIRECTORY_LEVEL)) {
1869 mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL,
1870 0, walk->write, 1, &walk->pt_write,
1871 walk->largepage, 0, gfn, walk->pfn, false);
1872 ++vcpu->stat.pf_fixed;
1873 return 1;
1874 }
1875 1856
1876 if (*sptep == shadow_trap_nonpresent_pte) { 1857 for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
1877 pseudo_gfn = (addr & PT64_DIR_BASE_ADDR_MASK) >> PAGE_SHIFT; 1858 if (iterator.level == PT_PAGE_TABLE_LEVEL
1878 sp = kvm_mmu_get_page(vcpu, pseudo_gfn, (gva_t)addr, level - 1, 1859 || (largepage && iterator.level == PT_DIRECTORY_LEVEL)) {
1879 1, ACC_ALL, sptep); 1860 mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL,
1880 if (!sp) { 1861 0, write, 1, &pt_write,
1881 pgprintk("nonpaging_map: ENOMEM\n"); 1862 largepage, 0, gfn, pfn, false);
1882 kvm_release_pfn_clean(walk->pfn); 1863 ++vcpu->stat.pf_fixed;
1883 return -ENOMEM; 1864 break;
1884 } 1865 }
1885 1866
1886 set_shadow_pte(sptep, 1867 if (*iterator.sptep == shadow_trap_nonpresent_pte) {
1887 __pa(sp->spt) 1868 pseudo_gfn = (iterator.addr & PT64_DIR_BASE_ADDR_MASK) >> PAGE_SHIFT;
1888 | PT_PRESENT_MASK | PT_WRITABLE_MASK 1869 sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr,
1889 | shadow_user_mask | shadow_x_mask); 1870 iterator.level - 1,
1890 } 1871 1, ACC_ALL, iterator.sptep);
1891 return 0; 1872 if (!sp) {
1892} 1873 pgprintk("nonpaging_map: ENOMEM\n");
1874 kvm_release_pfn_clean(pfn);
1875 return -ENOMEM;
1876 }
1893 1877
1894static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, 1878 set_shadow_pte(iterator.sptep,
1895 int largepage, gfn_t gfn, pfn_t pfn) 1879 __pa(sp->spt)
1896{ 1880 | PT_PRESENT_MASK | PT_WRITABLE_MASK
1897 int r; 1881 | shadow_user_mask | shadow_x_mask);
1898 struct direct_shadow_walk walker = { 1882 }
1899 .walker = { .entry = direct_map_entry, }, 1883 }
1900 .pfn = pfn, 1884 return pt_write;
1901 .largepage = largepage,
1902 .write = write,
1903 .pt_write = 0,
1904 };
1905
1906 r = walk_shadow(&walker.walker, vcpu, gfn << PAGE_SHIFT);
1907 if (r < 0)
1908 return r;
1909 return walker.pt_write;
1910} 1885}
1911 1886
1912static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn) 1887static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)