From owner-svn-src-all@freebsd.org Wed Jun 21 14:36:26 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 8EFE2D90F79; Wed, 21 Jun 2017 14:36:26 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::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 68F9B6F0A2; Wed, 21 Jun 2017 14:36:26 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v5LEaPas070410; Wed, 21 Jun 2017 14:36:25 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v5LEaP5A070409; Wed, 21 Jun 2017 14:36:25 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201706211436.v5LEaP5A070409@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Wed, 21 Jun 2017 14:36:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r320188 - stable/11/sys/vm X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jun 2017 14:36:26 -0000 Author: jhb Date: Wed Jun 21 14:36:25 2017 New Revision: 320188 URL: https://svnweb.freebsd.org/changeset/base/320188 Log: MFC 319702: Fix an off-by-one error in the VM page array on some systems. r313186 changed how the size of the VM page array was calculated to be less wasteful. For most systems, the amount of memory is divided by the overhead required by each page (a page of data plus a struct vm_page) to determine the maximum number of available pages. However, if the remainder for the first non-available page was at least a page of data (so that the only memory missing was a struct vm_page), this last page was left in phys_avail[] but was not allocated an entry in the VM page array. Handle this case by explicitly excluding the page from phys_avail[]. Approved by: re (kib) Modified: stable/11/sys/vm/vm_page.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/vm/vm_page.c ============================================================================== --- stable/11/sys/vm/vm_page.c Wed Jun 21 12:19:05 2017 (r320187) +++ stable/11/sys/vm/vm_page.c Wed Jun 21 14:36:25 2017 (r320188) @@ -561,8 +561,13 @@ vm_page_startup(vm_offset_t vaddr) size += vm_phys_segs[i].end - vm_phys_segs[i].start; for (i = 0; phys_avail[i + 1] != 0; i += 2) size += phys_avail[i + 1] - phys_avail[i]; - page_range = size / (PAGE_SIZE + sizeof(struct vm_page)); #elif defined(VM_PHYSSEG_DENSE) + size = high_avail - low_avail; +#else +#error "Either VM_PHYSSEG_DENSE or VM_PHYSSEG_SPARSE must be defined." +#endif + +#ifdef VM_PHYSSEG_DENSE /* * In the VM_PHYSSEG_DENSE case, the number of pages can account for * the overhead of a page structure per page only if vm_page_array is @@ -570,14 +575,27 @@ vm_page_startup(vm_offset_t vaddr) * allocate page structures representing the physical memory * underlying vm_page_array, even though they will not be used. */ - if (new_end == high_avail) - page_range = (high_avail - low_avail) / (PAGE_SIZE + - sizeof(struct vm_page)); + if (new_end != high_avail) + page_range = size / PAGE_SIZE; else - page_range = high_avail / PAGE_SIZE - first_page; -#else -#error "Either VM_PHYSSEG_DENSE or VM_PHYSSEG_SPARSE must be defined." #endif + { + page_range = size / (PAGE_SIZE + sizeof(struct vm_page)); + + /* + * If the partial bytes remaining are large enough for + * a page (PAGE_SIZE) without a corresponding + * 'struct vm_page', then new_end will contain an + * extra page after subtracting the length of the VM + * page array. Compensate by subtracting an extra + * page from new_end. + */ + if (size % (PAGE_SIZE + sizeof(struct vm_page)) >= PAGE_SIZE) { + if (new_end == high_avail) + high_avail -= PAGE_SIZE; + new_end -= PAGE_SIZE; + } + } end = new_end; /*