From owner-svn-src-user@FreeBSD.ORG Wed Feb 18 06:55:12 2015 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CAC6A884; Wed, 18 Feb 2015 06:55:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B515288C; Wed, 18 Feb 2015 06:55:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t1I6tCGF091999; Wed, 18 Feb 2015 06:55:12 GMT (envelope-from nwhitehorn@FreeBSD.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t1I6tCwX091997; Wed, 18 Feb 2015 06:55:12 GMT (envelope-from nwhitehorn@FreeBSD.org) Message-Id: <201502180655.t1I6tCwX091997@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: nwhitehorn set sender to nwhitehorn@FreeBSD.org using -f From: Nathan Whitehorn Date: Wed, 18 Feb 2015 06:55:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r278944 - in user/nwhitehorn/ppc64-pmap-rework: conf pseries X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Feb 2015 06:55:13 -0000 Author: nwhitehorn Date: Wed Feb 18 06:55:11 2015 New Revision: 278944 URL: https://svnweb.freebsd.org/changeset/base/278944 Log: Work around a bug in Linux KVM: the ability to unset referenced and changed bits in the page table doesn't exist despite these hypervisor calls being mandatory. To "fix" this, when asked to clear the bits, don't clear them and don't return the reference bit. This makes swap work at the expense of performance. It also results in pmap_ts_referenced() sometimes returning zero when the page has in fact been referenced. It is not clear to me whether this creates a problem beyond performance. In addition to adding a large warning banner if this issue is detected, I've sent a bug report to the PowerPC KVM list. Modified: user/nwhitehorn/ppc64-pmap-rework/conf/GENERIC64 user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c Modified: user/nwhitehorn/ppc64-pmap-rework/conf/GENERIC64 ============================================================================== --- user/nwhitehorn/ppc64-pmap-rework/conf/GENERIC64 Wed Feb 18 06:53:40 2015 (r278943) +++ user/nwhitehorn/ppc64-pmap-rework/conf/GENERIC64 Wed Feb 18 06:55:11 2015 (r278944) @@ -28,7 +28,7 @@ makeoptions WITH_CTF=1 # Platform support options POWERMAC #NewWorld Apple PowerMacs -options PS3 #Sony Playstation 3 +#options PS3 #Sony Playstation 3 options MAMBO #IBM Mambo Full System Simulator options PSERIES #PAPR-compliant systems (e.g. IBM p) Modified: user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c ============================================================================== --- user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c Wed Feb 18 06:53:40 2015 (r278943) +++ user/nwhitehorn/ppc64-pmap-rework/pseries/mmu_phyp.c Wed Feb 18 06:55:11 2015 (r278944) @@ -91,6 +91,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) { @@ -183,6 +200,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 @@ -231,6 +252,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 @@ -248,14 +270,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); }