Date: Fri, 20 Feb 2015 05:29:22 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r279042 - user/nwhitehorn/ppc64-pmap-rework/pseries Message-ID: <201502200529.t1K5TMNo039531@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Fri Feb 20 05:29:22 2015 New Revision: 279042 URL: https://svnweb.freebsd.org/changeset/base/279042 Log: Restore accidentally deleted broken KVM detection. This is being fixed upstream. Modified: user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c Modified: user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c ============================================================================== --- user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c Fri Feb 20 05:23:51 2015 (r279041) +++ user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c Fri Feb 20 05:29:22 2015 (r279042) @@ -89,6 +89,23 @@ static mmu_method_t mphyp_methods[] = { MMU_DEF_INHERIT(pseries_mmu, "mmu_phyp", mphyp_methods, 0, oea64_mmu); +static int brokenkvm = 0; + +static void +print_kvm_bug_warning(void *data) +{ + + if (brokenkvm) + printf("WARNING: Running on a broken hypervisor that does " + "not support mandatory H_CLEAR_MOD and H_CLEAR_REF " + "hypercalls. Performance will be suboptimal.\n"); +} + +SYSINIT(kvmbugwarn1, SI_SUB_COPYRIGHT, SI_ORDER_THIRD + 1, + print_kvm_bug_warning, NULL); +SYSINIT(kvmbugwarn2, SI_SUB_LAST, SI_ORDER_THIRD + 1, print_kvm_bug_warning, + NULL); + static void mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) { @@ -181,6 +198,10 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t moea64_mid_bootstrap(mmup, kernelstart, kernelend); moea64_late_bootstrap(mmup, kernelstart, kernelend); + + /* Test for broken versions of KVM that don't conform to the spec */ + if (phyp_hcall(H_CLEAR_MOD, 0, 0) == H_FUNCTION) + brokenkvm = 1; } static void @@ -229,6 +250,7 @@ mphyp_pte_clear(mmu_t mmu, struct pvo_en { int64_t refchg; uint64_t ptelo, junk; + int err; /* * This involves two steps (synch and clear) so we need the entry @@ -246,14 +268,28 @@ mphyp_pte_clear(mmu_t mmu, struct pvo_en return (refchg); } + if (brokenkvm) { + /* + * No way to clear either bit, which is total madness. + * Pessimistically claim that, once modified, it stays so + * forever and that it is never referenced. + */ + rw_runlock(&mphyp_eviction_lock); + return (refchg & ~LPTE_REF); + } + if (ptebit & LPTE_CHG) { - phyp_pft_hcall(H_CLEAR_MOD, 0, pvo->pvo_pte.slot, 0, 0, &ptelo, - &junk, &junk); + err = phyp_pft_hcall(H_CLEAR_MOD, 0, pvo->pvo_pte.slot, 0, 0, + &ptelo, &junk, &junk); + KASSERT(err == H_SUCCESS, + ("Error clearing page change bit: %d", err)); refchg |= (ptelo & LPTE_CHG); } if (ptebit & LPTE_REF) { - phyp_pft_hcall(H_CLEAR_REF, 0, pvo->pvo_pte.slot, 0, 0, &ptelo, - &junk, &junk); + err = phyp_pft_hcall(H_CLEAR_REF, 0, pvo->pvo_pte.slot, 0, 0, + &ptelo, &junk, &junk); + KASSERT(err == H_SUCCESS, + ("Error clearing page reference bit: %d", err)); refchg |= (ptelo & LPTE_REF); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502200529.t1K5TMNo039531>