From owner-svn-src-head@freebsd.org Tue Apr 2 18:50:53 2019 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5BCAF156FF90; Tue, 2 Apr 2019 18:50:53 +0000 (UTC) (envelope-from tychon@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id EF077720E7; Tue, 2 Apr 2019 18:50:52 +0000 (UTC) (envelope-from tychon@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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BB48121F0; Tue, 2 Apr 2019 18:50:49 +0000 (UTC) (envelope-from tychon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x32IonAV041954; Tue, 2 Apr 2019 18:50:49 GMT (envelope-from tychon@FreeBSD.org) Received: (from tychon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x32Iondm041953; Tue, 2 Apr 2019 18:50:49 GMT (envelope-from tychon@FreeBSD.org) Message-Id: <201904021850.x32Iondm041953@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tychon set sender to tychon@FreeBSD.org using -f From: Tycho Nightingale Date: Tue, 2 Apr 2019 18:50:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r345811 - head/sys/x86/iommu X-SVN-Group: head X-SVN-Commit-Author: tychon X-SVN-Commit-Paths: head/sys/x86/iommu X-SVN-Commit-Revision: 345811 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: EF077720E7 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.98)[-0.984,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Apr 2019 18:50:53 -0000 Author: tychon Date: Tue Apr 2 18:50:49 2019 New Revision: 345811 URL: https://svnweb.freebsd.org/changeset/base/345811 Log: DMAR driver assumes all physical addresses are backed by a fully initialized struct vm_page. Reviewed by: kib Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D19753 Modified: head/sys/x86/iommu/busdma_dmar.c Modified: head/sys/x86/iommu/busdma_dmar.c ============================================================================== --- head/sys/x86/iommu/busdma_dmar.c Tue Apr 2 18:50:33 2019 (r345810) +++ head/sys/x86/iommu/busdma_dmar.c Tue Apr 2 18:50:49 2019 (r345811) @@ -665,9 +665,9 @@ dmar_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmam { struct bus_dma_tag_dmar *tag; struct bus_dmamap_dmar *map; - vm_page_t *ma; - vm_paddr_t pstart, pend; - int error, i, ma_cnt, offset; + vm_page_t *ma, fma; + vm_paddr_t pstart, pend, paddr; + int error, i, ma_cnt, mflags, offset; tag = (struct bus_dma_tag_dmar *)dmat; map = (struct bus_dmamap_dmar *)map1; @@ -675,14 +675,36 @@ dmar_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmam pend = round_page(buf + buflen); offset = buf & PAGE_MASK; ma_cnt = OFF_TO_IDX(pend - pstart); - ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, map->cansleep ? - M_WAITOK : M_NOWAIT); + mflags = map->cansleep ? M_WAITOK : M_NOWAIT; + ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, mflags); if (ma == NULL) return (ENOMEM); - for (i = 0; i < ma_cnt; i++) - ma[i] = PHYS_TO_VM_PAGE(pstart + i * PAGE_SIZE); + fma = NULL; + for (i = 0; i < ma_cnt; i++) { + paddr = pstart + i * PAGE_SIZE; + ma[i] = PHYS_TO_VM_PAGE(paddr); + if (ma[i] == NULL || VM_PAGE_TO_PHYS(ma[i]) != paddr) { + /* + * If PHYS_TO_VM_PAGE() returned NULL or the + * vm_page was not initialized we'll use a + * fake page. + */ + if (fma == NULL) { + fma = malloc(sizeof(struct vm_page) * ma_cnt, + M_DEVBUF, mflags); + if (fma == NULL) { + free(ma, M_DEVBUF); + return (ENOMEM); + } + } + vm_page_initfake(&fma[i], pstart + i * PAGE_SIZE, + VM_MEMATTR_DEFAULT); + ma[i] = &fma[i]; + } + } error = dmar_bus_dmamap_load_something(tag, map, ma, offset, buflen, flags, segs, segp); + free(fma, M_DEVBUF); free(ma, M_DEVBUF); return (error); } @@ -696,7 +718,7 @@ dmar_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dm struct bus_dmamap_dmar *map; vm_page_t *ma, fma; vm_paddr_t pstart, pend, paddr; - int error, i, ma_cnt, offset; + int error, i, ma_cnt, mflags, offset; tag = (struct bus_dma_tag_dmar *)dmat; map = (struct bus_dmamap_dmar *)map1; @@ -704,41 +726,33 @@ dmar_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dm pend = round_page((vm_offset_t)buf + buflen); offset = (vm_offset_t)buf & PAGE_MASK; ma_cnt = OFF_TO_IDX(pend - pstart); - ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, map->cansleep ? - M_WAITOK : M_NOWAIT); + mflags = map->cansleep ? M_WAITOK : M_NOWAIT; + ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, mflags); if (ma == NULL) return (ENOMEM); - if (dumping) { - /* - * If dumping, do not attempt to call - * PHYS_TO_VM_PAGE() at all. It may return non-NULL - * but the vm_page returned might be not initialized, - * e.g. for the kernel itself. - */ - KASSERT(pmap == kernel_pmap, ("non-kernel address write")); - fma = malloc(sizeof(struct vm_page) * ma_cnt, M_DEVBUF, - M_ZERO | (map->cansleep ? M_WAITOK : M_NOWAIT)); - if (fma == NULL) { - free(ma, M_DEVBUF); - return (ENOMEM); - } - for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) { + fma = NULL; + for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) { + if (pmap == kernel_pmap) paddr = pmap_kextract(pstart); + else + paddr = pmap_extract(pmap, pstart); + ma[i] = PHYS_TO_VM_PAGE(paddr); + if (ma[i] == NULL || VM_PAGE_TO_PHYS(ma[i]) != paddr) { + /* + * If PHYS_TO_VM_PAGE() returned NULL or the + * vm_page was not initialized we'll use a + * fake page. + */ + if (fma == NULL) { + fma = malloc(sizeof(struct vm_page) * ma_cnt, + M_DEVBUF, mflags); + if (fma == NULL) { + free(ma, M_DEVBUF); + return (ENOMEM); + } + } vm_page_initfake(&fma[i], paddr, VM_MEMATTR_DEFAULT); ma[i] = &fma[i]; - } - } else { - fma = NULL; - for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) { - if (pmap == kernel_pmap) - paddr = pmap_kextract(pstart); - else - paddr = pmap_extract(pmap, pstart); - ma[i] = PHYS_TO_VM_PAGE(paddr); - KASSERT(VM_PAGE_TO_PHYS(ma[i]) == paddr, - ("PHYS_TO_VM_PAGE failed %jx %jx m %p", - (uintmax_t)paddr, (uintmax_t)VM_PAGE_TO_PHYS(ma[i]), - ma[i])); } } error = dmar_bus_dmamap_load_something(tag, map, ma, offset, buflen,