Skip to content

Commit cdb06e9

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM fixes from Radim Krčmář: "PPC: - Fix guest time accounting in the host - Fix large-page backing for radix guests on POWER9 - Fix HPT guests on POWER9 backed by 2M or 1G pages - Compile fixes for some configs and gcc versions s390: - Fix random memory corruption when running as guest2 (e.g. KVM in LPAR) and starting guest3 (e.g. nested KVM) with many CPUs - Export forgotten io interrupt delivery statistics counter" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: s390: fix memory overwrites when not using SCA entries KVM: PPC: Book3S HV: Fix guest time accounting with VIRT_CPU_ACCOUNTING_GEN KVM: PPC: Book3S HV: Fix VRMA initialization with 2MB or 1GB memory backing KVM: PPC: Book3S HV: Fix handling of large pages in radix page fault handler KVM: s390: provide io interrupt kvm_stat KVM: PPC: Book3S: Fix compile error that occurs with some gcc versions KVM: PPC: Fix compile error that occurs when CONFIG_ALTIVEC=n
2 parents 3961448 + 45e3b47 commit cdb06e9

File tree

4 files changed

+57
-35
lines changed

4 files changed

+57
-35
lines changed

arch/powerpc/kvm/book3s_64_mmu_radix.c

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ static void kvmppc_pte_free(pte_t *ptep)
195195
kmem_cache_free(kvm_pte_cache, ptep);
196196
}
197197

198+
/* Like pmd_huge() and pmd_large(), but works regardless of config options */
199+
static inline int pmd_is_leaf(pmd_t pmd)
200+
{
201+
return !!(pmd_val(pmd) & _PAGE_PTE);
202+
}
203+
198204
static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
199205
unsigned int level, unsigned long mmu_seq)
200206
{
@@ -219,7 +225,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
219225
else
220226
new_pmd = pmd_alloc_one(kvm->mm, gpa);
221227

222-
if (level == 0 && !(pmd && pmd_present(*pmd)))
228+
if (level == 0 && !(pmd && pmd_present(*pmd) && !pmd_is_leaf(*pmd)))
223229
new_ptep = kvmppc_pte_alloc();
224230

225231
/* Check if we might have been invalidated; let the guest retry if so */
@@ -244,12 +250,30 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
244250
new_pmd = NULL;
245251
}
246252
pmd = pmd_offset(pud, gpa);
247-
if (pmd_large(*pmd)) {
248-
/* Someone else has instantiated a large page here; retry */
249-
ret = -EAGAIN;
250-
goto out_unlock;
251-
}
252-
if (level == 1 && !pmd_none(*pmd)) {
253+
if (pmd_is_leaf(*pmd)) {
254+
unsigned long lgpa = gpa & PMD_MASK;
255+
256+
/*
257+
* If we raced with another CPU which has just put
258+
* a 2MB pte in after we saw a pte page, try again.
259+
*/
260+
if (level == 0 && !new_ptep) {
261+
ret = -EAGAIN;
262+
goto out_unlock;
263+
}
264+
/* Valid 2MB page here already, remove it */
265+
old = kvmppc_radix_update_pte(kvm, pmdp_ptep(pmd),
266+
~0UL, 0, lgpa, PMD_SHIFT);
267+
kvmppc_radix_tlbie_page(kvm, lgpa, PMD_SHIFT);
268+
if (old & _PAGE_DIRTY) {
269+
unsigned long gfn = lgpa >> PAGE_SHIFT;
270+
struct kvm_memory_slot *memslot;
271+
memslot = gfn_to_memslot(kvm, gfn);
272+
if (memslot && memslot->dirty_bitmap)
273+
kvmppc_update_dirty_map(memslot,
274+
gfn, PMD_SIZE);
275+
}
276+
} else if (level == 1 && !pmd_none(*pmd)) {
253277
/*
254278
* There's a page table page here, but we wanted
255279
* to install a large page. Tell the caller and let
@@ -412,28 +436,24 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
412436
} else {
413437
page = pages[0];
414438
pfn = page_to_pfn(page);
415-
if (PageHuge(page)) {
416-
page = compound_head(page);
417-
pte_size <<= compound_order(page);
439+
if (PageCompound(page)) {
440+
pte_size <<= compound_order(compound_head(page));
418441
/* See if we can insert a 2MB large-page PTE here */
419442
if (pte_size >= PMD_SIZE &&
420-
(gpa & PMD_MASK & PAGE_MASK) ==
421-
(hva & PMD_MASK & PAGE_MASK)) {
443+
(gpa & (PMD_SIZE - PAGE_SIZE)) ==
444+
(hva & (PMD_SIZE - PAGE_SIZE))) {
422445
level = 1;
423446
pfn &= ~((PMD_SIZE >> PAGE_SHIFT) - 1);
424447
}
425448
}
426449
/* See if we can provide write access */
427450
if (writing) {
428-
/*
429-
* We assume gup_fast has set dirty on the host PTE.
430-
*/
431451
pgflags |= _PAGE_WRITE;
432452
} else {
433453
local_irq_save(flags);
434454
ptep = find_current_mm_pte(current->mm->pgd,
435455
hva, NULL, NULL);
436-
if (ptep && pte_write(*ptep) && pte_dirty(*ptep))
456+
if (ptep && pte_write(*ptep))
437457
pgflags |= _PAGE_WRITE;
438458
local_irq_restore(flags);
439459
}
@@ -459,18 +479,15 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
459479
pte = pfn_pte(pfn, __pgprot(pgflags));
460480
ret = kvmppc_create_pte(kvm, pte, gpa, level, mmu_seq);
461481
}
462-
if (ret == 0 || ret == -EAGAIN)
463-
ret = RESUME_GUEST;
464482

465483
if (page) {
466-
/*
467-
* We drop pages[0] here, not page because page might
468-
* have been set to the head page of a compound, but
469-
* we have to drop the reference on the correct tail
470-
* page to match the get inside gup()
471-
*/
472-
put_page(pages[0]);
484+
if (!ret && (pgflags & _PAGE_WRITE))
485+
set_page_dirty_lock(page);
486+
put_page(page);
473487
}
488+
489+
if (ret == 0 || ret == -EAGAIN)
490+
ret = RESUME_GUEST;
474491
return ret;
475492
}
476493

@@ -644,7 +661,7 @@ void kvmppc_free_radix(struct kvm *kvm)
644661
continue;
645662
pmd = pmd_offset(pud, 0);
646663
for (im = 0; im < PTRS_PER_PMD; ++im, ++pmd) {
647-
if (pmd_huge(*pmd)) {
664+
if (pmd_is_leaf(*pmd)) {
648665
pmd_clear(pmd);
649666
continue;
650667
}

arch/powerpc/kvm/book3s_hv.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2885,16 +2885,14 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
28852885
*/
28862886
trace_hardirqs_on();
28872887

2888-
guest_enter();
2888+
guest_enter_irqoff();
28892889

28902890
srcu_idx = srcu_read_lock(&vc->kvm->srcu);
28912891

28922892
trap = __kvmppc_vcore_entry();
28932893

28942894
srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
28952895

2896-
guest_exit();
2897-
28982896
trace_hardirqs_off();
28992897
set_irq_happened(trap);
29002898

@@ -2937,6 +2935,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
29372935
kvmppc_set_host_core(pcpu);
29382936

29392937
local_irq_enable();
2938+
guest_exit();
29402939

29412940
/* Let secondaries go back to the offline loop */
29422941
for (i = 0; i < controlled_threads; ++i) {
@@ -3656,15 +3655,17 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
36563655
goto up_out;
36573656

36583657
psize = vma_kernel_pagesize(vma);
3659-
porder = __ilog2(psize);
36603658

36613659
up_read(&current->mm->mmap_sem);
36623660

36633661
/* We can handle 4k, 64k or 16M pages in the VRMA */
3664-
err = -EINVAL;
3665-
if (!(psize == 0x1000 || psize == 0x10000 ||
3666-
psize == 0x1000000))
3667-
goto out_srcu;
3662+
if (psize >= 0x1000000)
3663+
psize = 0x1000000;
3664+
else if (psize >= 0x10000)
3665+
psize = 0x10000;
3666+
else
3667+
psize = 0x1000;
3668+
porder = __ilog2(psize);
36683669

36693670
senc = slb_pgsize_encoding(psize);
36703671
kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |

arch/powerpc/kvm/powerpc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1345,7 +1345,7 @@ static int kvmppc_emulate_mmio_vsx_loadstore(struct kvm_vcpu *vcpu,
13451345
int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
13461346
unsigned int rt, int is_default_endian)
13471347
{
1348-
enum emulation_result emulated;
1348+
enum emulation_result emulated = EMULATE_DONE;
13491349

13501350
while (vcpu->arch.mmio_vmx_copy_nums) {
13511351
emulated = __kvmppc_handle_load(run, vcpu, rt, 8,
@@ -1608,7 +1608,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
16081608

16091609
kvm_sigset_deactivate(vcpu);
16101610

1611+
#ifdef CONFIG_ALTIVEC
16111612
out:
1613+
#endif
16121614
vcpu_put(vcpu);
16131615
return r;
16141616
}

arch/s390/kvm/kvm-s390.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
8686
{ "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
8787
{ "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
8888
{ "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
89+
{ "deliver_io_interrupt", VCPU_STAT(deliver_io_int) },
8990
{ "exit_wait_state", VCPU_STAT(exit_wait_state) },
9091
{ "instruction_epsw", VCPU_STAT(instruction_epsw) },
9192
{ "instruction_gs", VCPU_STAT(instruction_gs) },
@@ -2146,6 +2147,7 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
21462147
/* we still need the basic sca for the ipte control */
21472148
vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
21482149
vcpu->arch.sie_block->scaol = (__u32)(__u64)sca;
2150+
return;
21492151
}
21502152
read_lock(&vcpu->kvm->arch.sca_lock);
21512153
if (vcpu->kvm->arch.use_esca) {

0 commit comments

Comments
 (0)