History

Merge git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fix from Gleb Natapov: "Bugfix for the regression introduced by commit c300aa64ddf5" * git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: Allow cross page reads and writes from cached translations.

Linus Torvalds committed 13 years ago

Commit 875b7672 parents 39ab967 8f964525 files · +46 −19Browse files

Unified · Split

5 files
  1. arch/x86/kvm/lapic.c +1 −1
  2. arch/x86/kvm/x86.c +6 −7
  3. include/linux/kvm_host.h +1 −1
  4. include/linux/kvm_types.h +1 −0
  5. virt/kvm/kvm_main.c +37 −10
arch/x86/kvm/lapic.c+1−1
@@ -1857,7 +1857,7 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data) · 1856 unmodified lines
18571857 if (!pv_eoi_enabled(vcpu))
18581858 return 0;
18591859 return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data,
1860− addr);
1860+ addr, sizeof(u8));
18611861 }
18621862
18631863 void kvm_lapic_init(void)
arch/x86/kvm/x86.c+6−7
@@ -1823,7 +1823,8 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) · 1822 unmodified lines
18231823 return 0;
18241824 }
18251825
1826− if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa))
1826+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
1827+ sizeof(u32)))
18271828 return 1;
18281829
18291830 vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
@@ -1952,12 +1953,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 122 unmodified lines
19521953
19531954 gpa_offset = data & ~(PAGE_MASK | 1);
19541955
1955− /* Check that the address is 32-byte aligned. */
1956− if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1))
1957− break;
1958−
19591956 if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
1960− &vcpu->arch.pv_time, data & ~1ULL))
1957+ &vcpu->arch.pv_time, data & ~1ULL,
1958+ sizeof(struct pvclock_vcpu_time_info)))
19611959 vcpu->arch.pv_time_enabled = false;
19621960 else
19631961 vcpu->arch.pv_time_enabled = true;
@@ -1977,7 +1975,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 13 unmodified lines
19771975 return 1;
19781976
19791977 if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
1980− data & KVM_STEAL_VALID_BITS))
1978+ data & KVM_STEAL_VALID_BITS,
1979+ sizeof(struct kvm_steal_time)))
19811980 return 1;
19821981
19831982 vcpu->arch.st.msr_val = data;
include/linux/kvm_host.h+1−1
@@ -518,7 +518,7 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, · 517 unmodified lines
518518 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
519519 void *data, unsigned long len);
520520 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
521− gpa_t gpa);
521+ gpa_t gpa, unsigned long len);
522522 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
523523 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
524524 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
include/linux/kvm_types.h+1−0
@@ -71,6 +71,7 @@ struct gfn_to_hva_cache { · 70 unmodified lines
7171 u64 generation;
7272 gpa_t gpa;
7373 unsigned long hva;
74+ unsigned long len;
7475 struct kvm_memory_slot *memslot;
7576 };
7677
virt/kvm/kvm_main.c+37−10
@@ -1541,21 +1541,38 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, · 1540 unmodified lines
15411541 }
15421542
15431543 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
1544− gpa_t gpa)
1544+ gpa_t gpa, unsigned long len)
15451545 {
15461546 struct kvm_memslots *slots = kvm_memslots(kvm);
15471547 int offset = offset_in_page(gpa);
1548− gfn_t gfn = gpa >> PAGE_SHIFT;
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;
15491552
15501553 ghc->gpa = gpa;
15511554 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->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) {
15551559 ghc->hva += offset;
1556− else
1557− return -EFAULT;
1558−
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+ }
15591576 return 0;
15601577 }
15611578 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
@@ -1566,8 +1583,13 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, · 4 unmodified lines
15661583 struct kvm_memslots *slots = kvm_memslots(kvm);
15671584 int r;
15681585
1586+ BUG_ON(len > ghc->len);
1587+
15691588 if (slots->generation != ghc->generation)
1570− kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
1589+ kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
1590+
1591+ if (unlikely(!ghc->memslot))
1592+ return kvm_write_guest(kvm, ghc->gpa, data, len);
15711593
15721594 if (kvm_is_error_hva(ghc->hva))
15731595 return -EFAULT;
@@ -1587,8 +1609,13 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, · 13 unmodified lines
15871609 struct kvm_memslots *slots = kvm_memslots(kvm);
15881610 int r;
15891611
1612+ BUG_ON(len > ghc->len);
1613+
15901614 if (slots->generation != ghc->generation)
1591− kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
1615+ kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
1616+
1617+ if (unlikely(!ghc->memslot))
1618+ return kvm_read_guest(kvm, ghc->gpa, data, len);
15921619
15931620 if (kvm_is_error_hva(ghc->hva))
15941621 return -EFAULT;