mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-22 14:41:27 +00:00
Fixes for PPC KVM:
- 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJammR1AAoJEJ2a6ncsY3Gf2pQIAKf1sBKimpDj/yeBlWVbS41q 6mIJh8R+4DV7TcOSVoOdzUz1dU1cseVznqqr3kexu+unoUpcqm240ZUDsDNWy9j0 Xv0JyrGOcPor9sQmlb1s2gOsybxhic4u8Ih1eQV47bEUw1Rb84/da0JI1u5nMRTq nm3OHPGSnK2C8UkBBVjGelLJGUx+uaLFLjJSSTd0F9+hlxjGT3yXjP3wLG/ZNajT 6Reuzpr95hGpmIaml8gh73clLk4WAjF3+5SyiLo5nlsXzvMnC0DyzaUrHocIo6i7 nZxrx9UguzEdiUbuc5NEs4klTc+GPwMCfd+7z6vmtyw87A0sVOUgGWNGcZL60ew= =Wy2j -----END PGP SIGNATURE----- Merge tag 'kvm-ppc-fixes-4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc Fixes for PPC KVM: - 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
This commit is contained in:
commit
db5679379a
3 changed files with 55 additions and 35 deletions
|
@ -195,6 +195,12 @@ static void kvmppc_pte_free(pte_t *ptep)
|
||||||
kmem_cache_free(kvm_pte_cache, ptep);
|
kmem_cache_free(kvm_pte_cache, ptep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Like pmd_huge() and pmd_large(), but works regardless of config options */
|
||||||
|
static inline int pmd_is_leaf(pmd_t pmd)
|
||||||
|
{
|
||||||
|
return !!(pmd_val(pmd) & _PAGE_PTE);
|
||||||
|
}
|
||||||
|
|
||||||
static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
|
static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
|
||||||
unsigned int level, unsigned long mmu_seq)
|
unsigned int level, unsigned long mmu_seq)
|
||||||
{
|
{
|
||||||
|
@ -219,7 +225,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
|
||||||
else
|
else
|
||||||
new_pmd = pmd_alloc_one(kvm->mm, gpa);
|
new_pmd = pmd_alloc_one(kvm->mm, gpa);
|
||||||
|
|
||||||
if (level == 0 && !(pmd && pmd_present(*pmd)))
|
if (level == 0 && !(pmd && pmd_present(*pmd) && !pmd_is_leaf(*pmd)))
|
||||||
new_ptep = kvmppc_pte_alloc();
|
new_ptep = kvmppc_pte_alloc();
|
||||||
|
|
||||||
/* Check if we might have been invalidated; let the guest retry if so */
|
/* 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,
|
||||||
new_pmd = NULL;
|
new_pmd = NULL;
|
||||||
}
|
}
|
||||||
pmd = pmd_offset(pud, gpa);
|
pmd = pmd_offset(pud, gpa);
|
||||||
if (pmd_large(*pmd)) {
|
if (pmd_is_leaf(*pmd)) {
|
||||||
/* Someone else has instantiated a large page here; retry */
|
unsigned long lgpa = gpa & PMD_MASK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we raced with another CPU which has just put
|
||||||
|
* a 2MB pte in after we saw a pte page, try again.
|
||||||
|
*/
|
||||||
|
if (level == 0 && !new_ptep) {
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
if (level == 1 && !pmd_none(*pmd)) {
|
/* Valid 2MB page here already, remove it */
|
||||||
|
old = kvmppc_radix_update_pte(kvm, pmdp_ptep(pmd),
|
||||||
|
~0UL, 0, lgpa, PMD_SHIFT);
|
||||||
|
kvmppc_radix_tlbie_page(kvm, lgpa, PMD_SHIFT);
|
||||||
|
if (old & _PAGE_DIRTY) {
|
||||||
|
unsigned long gfn = lgpa >> PAGE_SHIFT;
|
||||||
|
struct kvm_memory_slot *memslot;
|
||||||
|
memslot = gfn_to_memslot(kvm, gfn);
|
||||||
|
if (memslot && memslot->dirty_bitmap)
|
||||||
|
kvmppc_update_dirty_map(memslot,
|
||||||
|
gfn, PMD_SIZE);
|
||||||
|
}
|
||||||
|
} else if (level == 1 && !pmd_none(*pmd)) {
|
||||||
/*
|
/*
|
||||||
* There's a page table page here, but we wanted
|
* There's a page table page here, but we wanted
|
||||||
* to install a large page. Tell the caller and let
|
* 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,
|
||||||
} else {
|
} else {
|
||||||
page = pages[0];
|
page = pages[0];
|
||||||
pfn = page_to_pfn(page);
|
pfn = page_to_pfn(page);
|
||||||
if (PageHuge(page)) {
|
if (PageCompound(page)) {
|
||||||
page = compound_head(page);
|
pte_size <<= compound_order(compound_head(page));
|
||||||
pte_size <<= compound_order(page);
|
|
||||||
/* See if we can insert a 2MB large-page PTE here */
|
/* See if we can insert a 2MB large-page PTE here */
|
||||||
if (pte_size >= PMD_SIZE &&
|
if (pte_size >= PMD_SIZE &&
|
||||||
(gpa & PMD_MASK & PAGE_MASK) ==
|
(gpa & (PMD_SIZE - PAGE_SIZE)) ==
|
||||||
(hva & PMD_MASK & PAGE_MASK)) {
|
(hva & (PMD_SIZE - PAGE_SIZE))) {
|
||||||
level = 1;
|
level = 1;
|
||||||
pfn &= ~((PMD_SIZE >> PAGE_SHIFT) - 1);
|
pfn &= ~((PMD_SIZE >> PAGE_SHIFT) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* See if we can provide write access */
|
/* See if we can provide write access */
|
||||||
if (writing) {
|
if (writing) {
|
||||||
/*
|
|
||||||
* We assume gup_fast has set dirty on the host PTE.
|
|
||||||
*/
|
|
||||||
pgflags |= _PAGE_WRITE;
|
pgflags |= _PAGE_WRITE;
|
||||||
} else {
|
} else {
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
ptep = find_current_mm_pte(current->mm->pgd,
|
ptep = find_current_mm_pte(current->mm->pgd,
|
||||||
hva, NULL, NULL);
|
hva, NULL, NULL);
|
||||||
if (ptep && pte_write(*ptep) && pte_dirty(*ptep))
|
if (ptep && pte_write(*ptep))
|
||||||
pgflags |= _PAGE_WRITE;
|
pgflags |= _PAGE_WRITE;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
@ -459,18 +479,15 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
pte = pfn_pte(pfn, __pgprot(pgflags));
|
pte = pfn_pte(pfn, __pgprot(pgflags));
|
||||||
ret = kvmppc_create_pte(kvm, pte, gpa, level, mmu_seq);
|
ret = kvmppc_create_pte(kvm, pte, gpa, level, mmu_seq);
|
||||||
}
|
}
|
||||||
if (ret == 0 || ret == -EAGAIN)
|
|
||||||
ret = RESUME_GUEST;
|
|
||||||
|
|
||||||
if (page) {
|
if (page) {
|
||||||
/*
|
if (!ret && (pgflags & _PAGE_WRITE))
|
||||||
* We drop pages[0] here, not page because page might
|
set_page_dirty_lock(page);
|
||||||
* have been set to the head page of a compound, but
|
put_page(page);
|
||||||
* we have to drop the reference on the correct tail
|
|
||||||
* page to match the get inside gup()
|
|
||||||
*/
|
|
||||||
put_page(pages[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == 0 || ret == -EAGAIN)
|
||||||
|
ret = RESUME_GUEST;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +661,7 @@ void kvmppc_free_radix(struct kvm *kvm)
|
||||||
continue;
|
continue;
|
||||||
pmd = pmd_offset(pud, 0);
|
pmd = pmd_offset(pud, 0);
|
||||||
for (im = 0; im < PTRS_PER_PMD; ++im, ++pmd) {
|
for (im = 0; im < PTRS_PER_PMD; ++im, ++pmd) {
|
||||||
if (pmd_huge(*pmd)) {
|
if (pmd_is_leaf(*pmd)) {
|
||||||
pmd_clear(pmd);
|
pmd_clear(pmd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2885,7 +2885,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||||
*/
|
*/
|
||||||
trace_hardirqs_on();
|
trace_hardirqs_on();
|
||||||
|
|
||||||
guest_enter();
|
guest_enter_irqoff();
|
||||||
|
|
||||||
srcu_idx = srcu_read_lock(&vc->kvm->srcu);
|
srcu_idx = srcu_read_lock(&vc->kvm->srcu);
|
||||||
|
|
||||||
|
@ -2893,8 +2893,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||||
|
|
||||||
srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
|
srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
|
||||||
|
|
||||||
guest_exit();
|
|
||||||
|
|
||||||
trace_hardirqs_off();
|
trace_hardirqs_off();
|
||||||
set_irq_happened(trap);
|
set_irq_happened(trap);
|
||||||
|
|
||||||
|
@ -2937,6 +2935,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||||
kvmppc_set_host_core(pcpu);
|
kvmppc_set_host_core(pcpu);
|
||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
guest_exit();
|
||||||
|
|
||||||
/* Let secondaries go back to the offline loop */
|
/* Let secondaries go back to the offline loop */
|
||||||
for (i = 0; i < controlled_threads; ++i) {
|
for (i = 0; i < controlled_threads; ++i) {
|
||||||
|
@ -3656,15 +3655,17 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
|
||||||
goto up_out;
|
goto up_out;
|
||||||
|
|
||||||
psize = vma_kernel_pagesize(vma);
|
psize = vma_kernel_pagesize(vma);
|
||||||
porder = __ilog2(psize);
|
|
||||||
|
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
|
||||||
/* We can handle 4k, 64k or 16M pages in the VRMA */
|
/* We can handle 4k, 64k or 16M pages in the VRMA */
|
||||||
err = -EINVAL;
|
if (psize >= 0x1000000)
|
||||||
if (!(psize == 0x1000 || psize == 0x10000 ||
|
psize = 0x1000000;
|
||||||
psize == 0x1000000))
|
else if (psize >= 0x10000)
|
||||||
goto out_srcu;
|
psize = 0x10000;
|
||||||
|
else
|
||||||
|
psize = 0x1000;
|
||||||
|
porder = __ilog2(psize);
|
||||||
|
|
||||||
senc = slb_pgsize_encoding(psize);
|
senc = slb_pgsize_encoding(psize);
|
||||||
kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
|
kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ static int kvmppc_emulate_mmio_vsx_loadstore(struct kvm_vcpu *vcpu,
|
||||||
int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
unsigned int rt, int is_default_endian)
|
unsigned int rt, int is_default_endian)
|
||||||
{
|
{
|
||||||
enum emulation_result emulated;
|
enum emulation_result emulated = EMULATE_DONE;
|
||||||
|
|
||||||
while (vcpu->arch.mmio_vmx_copy_nums) {
|
while (vcpu->arch.mmio_vmx_copy_nums) {
|
||||||
emulated = __kvmppc_handle_load(run, vcpu, rt, 8,
|
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)
|
||||||
|
|
||||||
kvm_sigset_deactivate(vcpu);
|
kvm_sigset_deactivate(vcpu);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ALTIVEC
|
||||||
out:
|
out:
|
||||||
|
#endif
|
||||||
vcpu_put(vcpu);
|
vcpu_put(vcpu);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue