KVM: Allow cross page reads and writes from cached translations.

This patch adds support for kvm_gfn_to_hva_cache_init functions for
reads and writes that will cross a page. If the range falls within
the same memslot, then this will be a fast operation. If the range
is split between two memslots, then the slower kvm_read_guest and
kvm_write_guest are used.

Tested: Test against kvm_clock unit tests.

Signed-off-by: Andrew Honig <ahonig@google.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>

authored by Andrew Honig and committed by Gleb Natapov 8f964525 09a6e1f4

+46 -19
+1 -1
arch/x86/kvm/lapic.c
··· 1857 if (!pv_eoi_enabled(vcpu)) 1858 return 0; 1859 return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data, 1860 - addr); 1861 } 1862 1863 void kvm_lapic_init(void)
··· 1857 if (!pv_eoi_enabled(vcpu)) 1858 return 0; 1859 return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data, 1860 + addr, sizeof(u8)); 1861 } 1862 1863 void kvm_lapic_init(void)
+6 -7
arch/x86/kvm/x86.c
··· 1823 return 0; 1824 } 1825 1826 - if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa)) 1827 return 1; 1828 1829 vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS); ··· 1953 1954 gpa_offset = data & ~(PAGE_MASK | 1); 1955 1956 - /* Check that the address is 32-byte aligned. */ 1957 - if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1)) 1958 - break; 1959 - 1960 if (kvm_gfn_to_hva_cache_init(vcpu->kvm, 1961 - &vcpu->arch.pv_time, data & ~1ULL)) 1962 vcpu->arch.pv_time_enabled = false; 1963 else 1964 vcpu->arch.pv_time_enabled = true; ··· 1975 return 1; 1976 1977 if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime, 1978 - data & KVM_STEAL_VALID_BITS)) 1979 return 1; 1980 1981 vcpu->arch.st.msr_val = data;
··· 1823 return 0; 1824 } 1825 1826 + if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa, 1827 + sizeof(u32))) 1828 return 1; 1829 1830 vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS); ··· 1952 1953 gpa_offset = data & ~(PAGE_MASK | 1); 1954 1955 if (kvm_gfn_to_hva_cache_init(vcpu->kvm, 1956 + &vcpu->arch.pv_time, data & ~1ULL, 1957 + sizeof(struct pvclock_vcpu_time_info))) 1958 vcpu->arch.pv_time_enabled = false; 1959 else 1960 vcpu->arch.pv_time_enabled = true; ··· 1977 return 1; 1978 1979 if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime, 1980 + data & KVM_STEAL_VALID_BITS, 1981 + sizeof(struct kvm_steal_time))) 1982 return 1; 1983 1984 vcpu->arch.st.msr_val = data;
+1 -1
include/linux/kvm_host.h
··· 518 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, 519 void *data, unsigned long len); 520 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, 521 - gpa_t gpa); 522 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); 523 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); 524 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
··· 518 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, 519 void *data, unsigned long len); 520 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, 521 + gpa_t gpa, unsigned long len); 522 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); 523 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); 524 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
+1
include/linux/kvm_types.h
··· 71 u64 generation; 72 gpa_t gpa; 73 unsigned long hva; 74 struct kvm_memory_slot *memslot; 75 }; 76
··· 71 u64 generation; 72 gpa_t gpa; 73 unsigned long hva; 74 + unsigned long len; 75 struct kvm_memory_slot *memslot; 76 }; 77
+37 -10
virt/kvm/kvm_main.c
··· 1541 } 1542 1543 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, 1544 - gpa_t gpa) 1545 { 1546 struct kvm_memslots *slots = kvm_memslots(kvm); 1547 int offset = offset_in_page(gpa); 1548 - gfn_t gfn = gpa >> PAGE_SHIFT; 1549 1550 ghc->gpa = gpa; 1551 ghc->generation = slots->generation; 1552 - ghc->memslot = gfn_to_memslot(kvm, gfn); 1553 - ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL); 1554 - if (!kvm_is_error_hva(ghc->hva)) 1555 ghc->hva += offset; 1556 - else 1557 - return -EFAULT; 1558 - 1559 return 0; 1560 } 1561 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init); ··· 1583 struct kvm_memslots *slots = kvm_memslots(kvm); 1584 int r; 1585 1586 if (slots->generation != ghc->generation) 1587 - kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa); 1588 1589 if (kvm_is_error_hva(ghc->hva)) 1590 return -EFAULT; ··· 1609 struct kvm_memslots *slots = kvm_memslots(kvm); 1610 int r; 1611 1612 if (slots->generation != ghc->generation) 1613 - kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa); 1614 1615 if (kvm_is_error_hva(ghc->hva)) 1616 return -EFAULT;
··· 1541 } 1542 1543 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, 1544 + gpa_t gpa, unsigned long len) 1545 { 1546 struct kvm_memslots *slots = kvm_memslots(kvm); 1547 int offset = offset_in_page(gpa); 1548 + gfn_t start_gfn = gpa >> PAGE_SHIFT; 1549 + gfn_t end_gfn = (gpa + len - 1) >> PAGE_SHIFT; 1550 + gfn_t nr_pages_needed = end_gfn - start_gfn + 1; 1551 + gfn_t nr_pages_avail; 1552 1553 ghc->gpa = gpa; 1554 ghc->generation = slots->generation; 1555 + ghc->len = len; 1556 + ghc->memslot = gfn_to_memslot(kvm, start_gfn); 1557 + ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail); 1558 + if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) { 1559 ghc->hva += offset; 1560 + } else { 1561 + /* 1562 + * If the requested region crosses two memslots, we still 1563 + * verify that the entire region is valid here. 1564 + */ 1565 + while (start_gfn <= end_gfn) { 1566 + ghc->memslot = gfn_to_memslot(kvm, start_gfn); 1567 + ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, 1568 + &nr_pages_avail); 1569 + if (kvm_is_error_hva(ghc->hva)) 1570 + return -EFAULT; 1571 + start_gfn += nr_pages_avail; 1572 + } 1573 + /* Use the slow path for cross page reads and writes. */ 1574 + ghc->memslot = NULL; 1575 + } 1576 return 0; 1577 } 1578 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init); ··· 1566 struct kvm_memslots *slots = kvm_memslots(kvm); 1567 int r; 1568 1569 + BUG_ON(len > ghc->len); 1570 + 1571 if (slots->generation != ghc->generation) 1572 + kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len); 1573 + 1574 + if (unlikely(!ghc->memslot)) 1575 + return kvm_write_guest(kvm, ghc->gpa, data, len); 1576 1577 if (kvm_is_error_hva(ghc->hva)) 1578 return -EFAULT; ··· 1587 struct kvm_memslots *slots = kvm_memslots(kvm); 1588 int r; 1589 1590 + BUG_ON(len > ghc->len); 1591 + 1592 if (slots->generation != ghc->generation) 1593 + kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len); 1594 + 1595 + if (unlikely(!ghc->memslot)) 1596 + return kvm_read_guest(kvm, ghc->gpa, data, len); 1597 1598 if (kvm_is_error_hva(ghc->hva)) 1599 return -EFAULT;