Index: .github/workflows/cross-bootstrap-tools.yml =================================================================== --- /dev/null +++ .github/workflows/cross-bootstrap-tools.yml @@ -0,0 +1,35 @@ +name: Cross-build CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04, macOS-latest] + + steps: + - uses: actions/checkout@v2 + - name: install LLVM+libarchive (Ubuntu) + run: | + wget -O /tmp/llvm.sh https://apt.llvm.org/llvm.sh + chmod +x /tmp/llvm.sh + sudo /tmp/llvm.sh 11 + sudo apt install -y libarchive-dev + echo "::set-env name=EXTRA_MAKE_ARGS::--cross-bindir=/usr/lib/llvm-11/bin" + if: ${{ startsWith(matrix.os, 'ubuntu') }} + - name: install LLVM+libarchive (macOS) + run: brew install llvm coreutils libarchive xz + if: ${{ startsWith(matrix.os, 'macOS') }} + - name: create build dir + run: rm -rf ../build && mkdir -p ../build + - name: make kernel-toolchain + run: env MAKEOBJDIRPREFIX=`realpath ../build` ./tools/build/make.py $EXTRA_MAKE_ARGS TARGET=amd64 TARGET_ARCH=amd64 kernel-toolchain -s -j$(nproc) + - name: make buildkernel + run: env MAKEOBJDIRPREFIX=`realpath ../build` ./tools/build/make.py $EXTRA_MAKE_ARGS TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC NO_MODULES=yes buildkernel -s -j$(nproc) Index: ObsoleteFiles.inc =================================================================== --- ObsoleteFiles.inc +++ ObsoleteFiles.inc @@ -36,6 +36,9 @@ # xargs -n1 | sort | uniq -d; # done +# 20200923: memfd_test moved to /usr/tests/sys/posixshm +OLD_FILES+=usr/tests/sys/kern/memfd_test + # 20200910: remove vm_map_create(9) to sync with the code OLD_FILES+=usr/share/man/man9/vm_map_create.9.gz Index: contrib/byacc/closure.c =================================================================== --- contrib/byacc/closure.c +++ contrib/byacc/closure.c @@ -87,7 +87,7 @@ k = 0; } - if (cword & (unsigned)(1 << k)) + if (cword & (1u << k)) { rp = derives[j]; while ((rule = *rp++) >= 0) @@ -151,7 +151,7 @@ { for (i = 0; i < BITS_PER_WORD; ++i) { - if (word & (unsigned)(1 << i)) + if (word & (1u << i)) { itemno = rrhs[ruleno + i]; while (csp < csend && *csp < itemno) Index: contrib/byacc/warshall.c =================================================================== --- contrib/byacc/warshall.c +++ contrib/byacc/warshall.c @@ -28,7 +28,7 @@ while (rowj < relend) { - if (*ccol & (unsigned)(1 << i)) + if (*ccol & (1u << i)) { rp = rowi; rend = rowj + rowsize; @@ -70,7 +70,7 @@ rp = R; while (rp < relend) { - *rp |= (unsigned)(1 << i); + *rp |= (1u << i); if (++i >= BITS_PER_WORD) { i = 0; Index: sbin/reboot/nextboot.sh =================================================================== --- sbin/reboot/nextboot.sh +++ sbin/reboot/nextboot.sh @@ -116,7 +116,7 @@ nextboot_tmp=$(mktemp $(dirname ${nextboot_file})/nextboot.XXXXXX) -if [ -n ${zfs} ]; then +if [ -n "${zfs}" ]; then zfsbootcfg -z ${zfs} -n freebsd:nvstore -k nextboot_enable -v YES cat >> ${nextboot_tmp} << EOF $kenv Index: share/man/man5/src.conf.5 =================================================================== --- share/man/man5/src.conf.5 +++ share/man/man5/src.conf.5 @@ -669,10 +669,10 @@ This is a default setting on amd64/amd64, arm/armv6, arm/armv7, i386/i386, mips/mips, mips/mips64, powerpc/powerpc and powerpc/powerpc64. .It Va WITHOUT_GH_BC -Do not install the enhanced -.Xr bc +Set to not build and install the enhanced +.Xr bc 1 and -.Xr dc +.Xr dc 1 programs instead of the traditional FreeBSD versions. .It Va WITHOUT_GNU_DIFF Set to not build GNU Index: share/man/man9/devctl_notify.9 =================================================================== --- share/man/man9/devctl_notify.9 +++ share/man/man9/devctl_notify.9 @@ -1,8 +1,6 @@ .\" .\" Copyright (c) 2020 M Warner Losh .\" -.\" This program is free software. -.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: Index: share/man/man9/devctl_process_running.9 =================================================================== --- share/man/man9/devctl_process_running.9 +++ share/man/man9/devctl_process_running.9 @@ -1,8 +1,6 @@ .\" .\" Copyright (c) 2020 M Warner Losh .\" -.\" This program is free software. -.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: Index: share/man/man9/devctl_safe_quote_sb.9 =================================================================== --- share/man/man9/devctl_safe_quote_sb.9 +++ share/man/man9/devctl_safe_quote_sb.9 @@ -1,8 +1,6 @@ .\" .\" Copyright (c) 2020 M Warner Losh .\" -.\" This program is free software. -.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: @@ -38,12 +36,12 @@ .Fn devctl_safe_quote_sb "struct sbuf *sb" "const char *src" .Sh DESCRIPTION Copy the string from -.Vn src +.Va src into -.Vn sb . +.Va sb . All backslash characters are doubled. All double quote characters -.Sq " +.Sq \&" are also preceded by a backslash. All other characters are copied without modification. The Index: stand/efi/loader/main.c =================================================================== --- stand/efi/loader/main.c +++ stand/efi/loader/main.c @@ -36,7 +36,9 @@ #include #include #include +#ifdef EFI_ZFS_BOOT #include +#endif #include #include #include Index: stand/i386/loader/main.c =================================================================== --- stand/i386/loader/main.c +++ stand/i386/loader/main.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include "bootstrap.h" @@ -50,6 +49,7 @@ #include "btxv86.h" #ifdef LOADER_ZFS_SUPPORT +#include #include "libzfs.h" #endif Index: stand/i386/zfsboot/zfsboot.c =================================================================== --- stand/i386/zfsboot/zfsboot.c +++ stand/i386/zfsboot/zfsboot.c @@ -26,7 +26,9 @@ #endif #include #include +#ifdef LOADER_ZFS_SUPPORT #include +#endif #include #include Index: sys/amd64/conf/NOTES =================================================================== --- sys/amd64/conf/NOTES +++ sys/amd64/conf/NOTES @@ -125,8 +125,8 @@ # MISCELLANEOUS DEVICES AND OPTIONS device speaker #Play IBM BASIC-style noises out your speaker -hint.speaker.0.at="isa" -hint.speaker.0.port="0x61" +envvar hint.speaker.0.at="isa" +envvar hint.speaker.0.port="0x61" ##################################################################### @@ -199,8 +199,8 @@ # PS/2 mouse device psm -hint.psm.0.at="atkbdc" -hint.psm.0.irq="12" +envvar hint.psm.0.at="atkbdc" +envvar hint.psm.0.irq="12" # Options for psm: options PSM_HOOKRESUME #hook the system resume event, useful @@ -209,13 +209,13 @@ # The keyboard controller; it controls the keyboard and the PS/2 mouse. device atkbdc -hint.atkbdc.0.at="isa" -hint.atkbdc.0.port="0x060" +envvar hint.atkbdc.0.at="isa" +envvar hint.atkbdc.0.port="0x060" # The AT keyboard device atkbd -hint.atkbd.0.at="atkbdc" -hint.atkbd.0.irq="1" +envvar hint.atkbd.0.at="atkbdc" +envvar hint.atkbd.0.irq="1" # Options for atkbd: options ATKBD_DFLT_KEYMAP # specify the built-in keymap @@ -230,7 +230,7 @@ # Video card driver for VGA adapters. device vga -hint.vga.0.at="isa" +envvar hint.vga.0.at="isa" # Options for vga: # Try the following option if the mouse pointer is not drawn correctly @@ -523,8 +523,8 @@ device ipmi device pbio -hint.pbio.0.at="isa" -hint.pbio.0.port="0x360" +envvar hint.pbio.0.at="isa" +envvar hint.pbio.0.port="0x360" device smbios device vpd device asmc Index: sys/amd64/include/vmparam.h =================================================================== --- sys/amd64/include/vmparam.h +++ sys/amd64/include/vmparam.h @@ -253,6 +253,11 @@ */ #define VM_BATCHQUEUE_SIZE 31 +/* + * The pmap can create non-transparent large page mappings. + */ +#define PMAP_HAS_LARGEPAGES 1 + /* * Need a page dump array for minidump. */ Index: sys/arm/include/vmparam.h =================================================================== --- sys/arm/include/vmparam.h +++ sys/arm/include/vmparam.h @@ -193,6 +193,11 @@ #define DEVMAP_MAX_VADDR ARM_VECTORS_HIGH +/* + * No non-transparent large page support in the pmap. + */ +#define PMAP_HAS_LARGEPAGES 0 + /* * Need a page dump array for minidump. */ Index: sys/arm64/arm64/busdma_bounce.c =================================================================== --- sys/arm64/arm64/busdma_bounce.c +++ sys/arm64/arm64/busdma_bounce.c @@ -72,6 +72,8 @@ struct bus_dma_tag { struct bus_dma_tag_common common; + size_t alloc_size; + size_t alloc_alignment; int map_count; int bounce_flags; bus_dma_segment_t *segments; @@ -135,8 +137,9 @@ void *callback_arg; STAILQ_ENTRY(bus_dmamap) links; u_int flags; -#define DMAMAP_COULD_BOUNCE (1 << 0) +#define DMAMAP_COHERENT (1 << 0) #define DMAMAP_FROM_DMAMEM (1 << 1) +#define DMAMAP_MBUF (1 << 2) int sync_count; struct sync_list slist[]; }; @@ -153,8 +156,8 @@ vm_offset_t vaddr, bus_addr_t addr, bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr); -static bool _bus_dmamap_pagesneeded(bus_dma_tag_t dmat, vm_paddr_t buf, - bus_size_t buflen, int *pagesneeded); +static bool _bus_dmamap_pagesneeded(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int *pagesneeded); static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, void *buf, bus_size_t buflen, int flags); static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, @@ -162,6 +165,77 @@ static int _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags); +/* + * Return true if the DMA should bounce because the start or end does not fall + * on a cacheline boundary (which would require a partial cacheline flush). + * COHERENT memory doesn't trigger cacheline flushes. Memory allocated by + * bus_dmamem_alloc() is always aligned to cacheline boundaries, and there's a + * strict rule that such memory cannot be accessed by the CPU while DMA is in + * progress (or by multiple DMA engines at once), so that it's always safe to do + * full cacheline flushes even if that affects memory outside the range of a + * given DMA operation that doesn't involve the full allocated buffer. If we're + * mapping an mbuf, that follows the same rules as a buffer we allocated. + */ +static bool +cacheline_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr, + bus_size_t size) +{ + +#define DMAMAP_CACHELINE_FLAGS \ + (DMAMAP_FROM_DMAMEM | DMAMAP_COHERENT | DMAMAP_MBUF) + if ((dmat->bounce_flags & BF_COHERENT) != 0) + return (false); + if (map != NULL && (map->flags & DMAMAP_CACHELINE_FLAGS) != 0) + return (false); + return (((paddr | size) & (dcache_line_size - 1)) != 0); +#undef DMAMAP_CACHELINE_FLAGS +} + +/* + * Return true if the given address does not fall on the alignment boundary. + */ +static bool +alignment_bounce(bus_dma_tag_t dmat, bus_addr_t addr) +{ + + return ((addr & (dmat->common.alignment - 1)) != 0); +} + +static bool +might_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr, + bus_size_t size) +{ + + if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0) + return (true); + + if (cacheline_bounce(dmat, map, paddr, size)) + return (true); + + if (alignment_bounce(dmat, paddr)) + return (true); + + return (false); +} + +static bool +must_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr, + bus_size_t size) +{ + + if (cacheline_bounce(dmat, map, paddr, size)) + return (true); + + if (alignment_bounce(dmat, paddr)) + return (true); + + if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0 && + bus_dma_run_filter(&dmat->common, paddr)) + return (true); + + return (false); +} + /* * Allocate a device specific dma_tag. */ @@ -187,8 +261,22 @@ newtag->map_count = 0; newtag->segments = NULL; - if ((flags & BUS_DMA_COHERENT) != 0) + if ((flags & BUS_DMA_COHERENT) != 0) { newtag->bounce_flags |= BF_COHERENT; + newtag->alloc_alignment = newtag->common.alignment; + newtag->alloc_size = newtag->common.maxsize; + } else { + /* + * Ensure the buffer is aligned to a cacheline when allocating + * a non-coherent buffer. This is so we don't have any data + * that another CPU may be accessing around DMA buffer + * causing the cache to become dirty. + */ + newtag->alloc_alignment = MAX(newtag->common.alignment, + dcache_line_size); + newtag->alloc_size = roundup2(newtag->common.maxsize, + dcache_line_size); + } if (parent != NULL) { if ((newtag->common.filter != NULL || @@ -203,8 +291,7 @@ newtag->common.alignment > 1) newtag->bounce_flags |= BF_COULD_BOUNCE; - if (((newtag->bounce_flags & BF_COULD_BOUNCE) != 0) && - (flags & BUS_DMA_ALLOCNOW) != 0) { + if ((flags & BUS_DMA_ALLOCNOW) != 0) { struct bounce_zone *bz; /* Must bounce */ @@ -278,9 +365,9 @@ bounce_bus_dma_id_mapped(bus_dma_tag_t dmat, vm_paddr_t buf, bus_size_t buflen) { - if ((dmat->bounce_flags & BF_COULD_BOUNCE) == 0) + if (!might_bounce(dmat, NULL, buf, buflen)) return (true); - return (!_bus_dmamap_pagesneeded(dmat, buf, buflen, NULL)); + return (!_bus_dmamap_pagesneeded(dmat, NULL, buf, buflen, NULL)); } static bus_dmamap_t @@ -336,49 +423,46 @@ * exclusion region, a data alignment that is stricter than 1, and/or * an active address boundary. */ - if (dmat->bounce_flags & BF_COULD_BOUNCE) { - /* Must bounce */ - if (dmat->bounce_zone == NULL) { - if ((error = alloc_bounce_zone(dmat)) != 0) { - free(*mapp, M_DEVBUF); - return (error); - } + if (dmat->bounce_zone == NULL) { + if ((error = alloc_bounce_zone(dmat)) != 0) { + free(*mapp, M_DEVBUF); + return (error); } - bz = dmat->bounce_zone; - - (*mapp)->flags = DMAMAP_COULD_BOUNCE; + } + bz = dmat->bounce_zone; - /* - * Attempt to add pages to our pool on a per-instance - * basis up to a sane limit. - */ - if (dmat->common.alignment > 1) - maxpages = MAX_BPAGES; - else - maxpages = MIN(MAX_BPAGES, Maxmem - - atop(dmat->common.lowaddr)); - if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0 || - (bz->map_count > 0 && bz->total_bpages < maxpages)) { - pages = MAX(atop(dmat->common.maxsize), 1); - pages = MIN(maxpages - bz->total_bpages, pages); - pages = MAX(pages, 1); - if (alloc_bounce_pages(dmat, pages) < pages) - error = ENOMEM; - if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) - == 0) { - if (error == 0) { - dmat->bounce_flags |= - BF_MIN_ALLOC_COMP; - } - } else - error = 0; - } - bz->map_count++; + /* + * Attempt to add pages to our pool on a per-instance + * basis up to a sane limit. + */ + if (dmat->common.alignment > 1) + maxpages = MAX_BPAGES; + else + maxpages = MIN(MAX_BPAGES, Maxmem - + atop(dmat->common.lowaddr)); + if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0 || + (bz->map_count > 0 && bz->total_bpages < maxpages)) { + pages = MAX(atop(dmat->common.maxsize), 1); + pages = MIN(maxpages - bz->total_bpages, pages); + pages = MAX(pages, 1); + if (alloc_bounce_pages(dmat, pages) < pages) + error = ENOMEM; + if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0) { + if (error == 0) { + dmat->bounce_flags |= BF_MIN_ALLOC_COMP; + } + } else + error = 0; } - if (error == 0) + bz->map_count++; + + if (error == 0) { dmat->map_count++; - else + if ((dmat->bounce_flags & BF_COHERENT) != 0) + (*mapp)->flags |= DMAMAP_COHERENT; + } else { free(*mapp, M_DEVBUF); + } CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", __func__, dmat, dmat->common.flags, error); return (error); @@ -400,11 +484,8 @@ CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, EBUSY); return (EBUSY); } - if (dmat->bounce_zone) { - KASSERT((map->flags & DMAMAP_COULD_BOUNCE) != 0, - ("%s: Bounce zone when cannot bounce", __func__)); + if (dmat->bounce_zone) dmat->bounce_zone->map_count--; - } free(map, M_DEVBUF); dmat->map_count--; CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat); @@ -469,7 +550,16 @@ __func__, dmat, dmat->common.flags, ENOMEM); return (ENOMEM); } - (*mapp)->flags = DMAMAP_FROM_DMAMEM; + + /* + * Mark the map as coherent if we used uncacheable memory or the + * tag was already marked as coherent. + */ + if (attr == VM_MEMATTR_UNCACHEABLE || + (dmat->bounce_flags & BF_COHERENT) != 0) + (*mapp)->flags |= DMAMAP_COHERENT; + + (*mapp)->flags |= DMAMAP_FROM_DMAMEM; /* * Allocate the buffer from the malloc(9) allocator if... @@ -492,23 +582,23 @@ * * In the meantime warn the user if malloc gets it wrong. */ - if ((dmat->common.maxsize <= PAGE_SIZE) && - (dmat->common.alignment <= dmat->common.maxsize) && + if ((dmat->alloc_size <= PAGE_SIZE) && + (dmat->alloc_alignment <= dmat->alloc_size) && dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) && attr == VM_MEMATTR_DEFAULT) { - *vaddr = malloc(dmat->common.maxsize, M_DEVBUF, mflags); + *vaddr = malloc(dmat->alloc_size, M_DEVBUF, mflags); } else if (dmat->common.nsegments >= - howmany(dmat->common.maxsize, MIN(dmat->common.maxsegsz, PAGE_SIZE)) && - dmat->common.alignment <= PAGE_SIZE && + howmany(dmat->alloc_size, MIN(dmat->common.maxsegsz, PAGE_SIZE)) && + dmat->alloc_alignment <= PAGE_SIZE && (dmat->common.boundary % PAGE_SIZE) == 0) { /* Page-based multi-segment allocations allowed */ - *vaddr = (void *)kmem_alloc_attr(dmat->common.maxsize, mflags, + *vaddr = (void *)kmem_alloc_attr(dmat->alloc_size, mflags, 0ul, dmat->common.lowaddr, attr); dmat->bounce_flags |= BF_KMEM_ALLOC; } else { - *vaddr = (void *)kmem_alloc_contig(dmat->common.maxsize, mflags, - 0ul, dmat->common.lowaddr, dmat->common.alignment != 0 ? - dmat->common.alignment : 1ul, dmat->common.boundary, attr); + *vaddr = (void *)kmem_alloc_contig(dmat->alloc_size, mflags, + 0ul, dmat->common.lowaddr, dmat->alloc_alignment != 0 ? + dmat->alloc_alignment : 1ul, dmat->common.boundary, attr); dmat->bounce_flags |= BF_KMEM_ALLOC; } if (*vaddr == NULL) { @@ -516,7 +606,7 @@ __func__, dmat, dmat->common.flags, ENOMEM); free(*mapp, M_DEVBUF); return (ENOMEM); - } else if (vtophys(*vaddr) & (dmat->common.alignment - 1)) { + } else if (vtophys(*vaddr) & (dmat->alloc_alignment - 1)) { printf("bus_dmamem_alloc failed to align memory properly.\n"); } dmat->map_count++; @@ -543,7 +633,7 @@ if ((dmat->bounce_flags & BF_KMEM_ALLOC) == 0) free(vaddr, M_DEVBUF); else - kmem_free((vm_offset_t)vaddr, dmat->common.maxsize); + kmem_free((vm_offset_t)vaddr, dmat->alloc_size); free(map, M_DEVBUF); dmat->map_count--; CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, @@ -551,8 +641,8 @@ } static bool -_bus_dmamap_pagesneeded(bus_dma_tag_t dmat, vm_paddr_t buf, bus_size_t buflen, - int *pagesneeded) +_bus_dmamap_pagesneeded(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int *pagesneeded) { bus_addr_t curaddr; bus_size_t sgsize; @@ -566,7 +656,7 @@ curaddr = buf; while (buflen != 0) { sgsize = MIN(buflen, dmat->common.maxsegsz); - if (bus_dma_run_filter(&dmat->common, curaddr)) { + if (must_bounce(dmat, map, curaddr, sgsize)) { sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK)); if (pagesneeded == NULL) @@ -587,8 +677,9 @@ bus_size_t buflen, int flags) { - if ((map->flags & DMAMAP_COULD_BOUNCE) != 0 && map->pagesneeded == 0) { - _bus_dmamap_pagesneeded(dmat, buf, buflen, &map->pagesneeded); + if (map->pagesneeded == 0) { + _bus_dmamap_pagesneeded(dmat, map, buf, buflen, + &map->pagesneeded); CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); } } @@ -602,7 +693,7 @@ bus_addr_t paddr; bus_size_t sg_len; - if ((map->flags & DMAMAP_COULD_BOUNCE) != 0 && map->pagesneeded == 0) { + if (map->pagesneeded == 0) { CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, " "alignment= %d", dmat->common.lowaddr, ptoa((vm_paddr_t)Maxmem), @@ -622,7 +713,9 @@ paddr = pmap_kextract(vaddr); else paddr = pmap_extract(pmap, vaddr); - if (bus_dma_run_filter(&dmat->common, paddr) != 0) { + if (must_bounce(dmat, map, paddr, + min(vendaddr - vaddr, (PAGE_SIZE - ((vm_offset_t)vaddr & + PAGE_MASK)))) != 0) { sg_len = roundup2(sg_len, dmat->common.alignment); map->pagesneeded++; @@ -720,7 +813,7 @@ if (segs == NULL) segs = dmat->segments; - if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0) { + if (might_bounce(dmat, map, (bus_addr_t)buf, buflen)) { _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); if (map->pagesneeded != 0) { error = _bus_dmamap_reserve_pages(dmat, map, flags); @@ -735,13 +828,12 @@ while (buflen > 0) { curaddr = buf; sgsize = MIN(buflen, dmat->common.maxsegsz); - if (((dmat->bounce_flags & BF_COULD_BOUNCE) != 0) && - map->pagesneeded != 0 && - bus_dma_run_filter(&dmat->common, curaddr)) { + if (map->pagesneeded != 0 && + must_bounce(dmat, map, curaddr, sgsize)) { sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK)); curaddr = add_bounce_page(dmat, map, 0, curaddr, sgsize); - } else if ((dmat->bounce_flags & BF_COHERENT) == 0) { + } else if ((map->flags & DMAMAP_COHERENT) == 0) { if (map->sync_count > 0) sl_end = sl->paddr + sl->datacount; @@ -791,7 +883,10 @@ if (segs == NULL) segs = dmat->segments; - if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0) { + if (flags & BUS_DMA_LOAD_MBUF) + map->flags |= DMAMAP_MBUF; + + if (might_bounce(dmat, map, (bus_addr_t)buf, buflen)) { _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); if (map->pagesneeded != 0) { error = _bus_dmamap_reserve_pages(dmat, map, flags); @@ -822,14 +917,13 @@ */ max_sgsize = MIN(buflen, dmat->common.maxsegsz); sgsize = PAGE_SIZE - (curaddr & PAGE_MASK); - if (((dmat->bounce_flags & BF_COULD_BOUNCE) != 0) && - map->pagesneeded != 0 && - bus_dma_run_filter(&dmat->common, curaddr)) { + if (map->pagesneeded != 0 && + must_bounce(dmat, map, curaddr, sgsize)) { sgsize = roundup2(sgsize, dmat->common.alignment); sgsize = MIN(sgsize, max_sgsize); curaddr = add_bounce_page(dmat, map, kvaddr, curaddr, sgsize); - } else if ((dmat->bounce_flags & BF_COHERENT) == 0) { + } else if ((map->flags & DMAMAP_COHERENT) == 0) { sgsize = MIN(sgsize, max_sgsize); if (map->sync_count > 0) { sl_pend = sl->paddr + sl->datacount; @@ -879,8 +973,6 @@ struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { - if ((map->flags & DMAMAP_COULD_BOUNCE) == 0) - return; map->mem = *mem; map->dmat = dmat; map->callback = callback; @@ -911,6 +1003,7 @@ } map->sync_count = 0; + map->flags &= ~DMAMAP_MBUF; } static void @@ -1025,7 +1118,7 @@ (void *)bpage->vaddr, bpage->datacount); if (tempvaddr != 0) pmap_quick_remove_page(tempvaddr); - if ((dmat->bounce_flags & BF_COHERENT) == 0) + if ((map->flags & DMAMAP_COHERENT) == 0) cpu_dcache_wb_range(bpage->vaddr, bpage->datacount); bpage = STAILQ_NEXT(bpage, links); @@ -1033,7 +1126,7 @@ dmat->bounce_zone->total_bounced++; } else if ((op & BUS_DMASYNC_PREREAD) != 0) { while (bpage != NULL) { - if ((dmat->bounce_flags & BF_COHERENT) == 0) + if ((map->flags & DMAMAP_COHERENT) == 0) cpu_dcache_wbinv_range(bpage->vaddr, bpage->datacount); bpage = STAILQ_NEXT(bpage, links); @@ -1042,7 +1135,7 @@ if ((op & BUS_DMASYNC_POSTREAD) != 0) { while (bpage != NULL) { - if ((dmat->bounce_flags & BF_COHERENT) == 0) + if ((map->flags & DMAMAP_COHERENT) == 0) cpu_dcache_inv_range(bpage->vaddr, bpage->datacount); tempvaddr = 0; @@ -1247,8 +1340,6 @@ struct bounce_page *bpage; KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag")); - KASSERT((map->flags & DMAMAP_COULD_BOUNCE) != 0, - ("add_bounce_page: bad map %p", map)); bz = dmat->bounce_zone; if (map->pagesneeded == 0) Index: sys/arm64/arm64/pmap.c =================================================================== --- sys/arm64/arm64/pmap.c +++ sys/arm64/arm64/pmap.c @@ -177,6 +177,8 @@ #define PV_STAT(x) do { } while (0) #endif +#define pmap_l0_pindex(v) (NUL2E + NUL1E + ((v) >> L0_SHIFT)) +#define pmap_l1_pindex(v) (NUL2E + ((v) >> L1_SHIFT)) #define pmap_l2_pindex(v) ((v) >> L2_SHIFT) static struct md_page * @@ -1087,6 +1089,9 @@ KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, ("pmap_init: can't assign to pagesizes[1]")); pagesizes[1] = L2_SIZE; + KASSERT(MAXPAGESIZES > 2 && pagesizes[2] == 0, + ("pmap_init: can't assign to pagesizes[2]")); + pagesizes[2] = L1_SIZE; } /* @@ -1337,7 +1342,7 @@ use = true; if (use) { - switch(lvl) { + switch (lvl) { case 1: off = va & L1_OFFSET; break; @@ -1349,7 +1354,7 @@ off = 0; } m = PHYS_TO_VM_PAGE((tpte & ~ATTR_MASK) | off); - if (!vm_page_wire_mapped(m)) + if (m != NULL && !vm_page_wire_mapped(m)) m = NULL; } } @@ -2968,11 +2973,23 @@ continue; } + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; l1 = pmap_l0_to_l1(l0, sva); - if (pmap_load(l1) == 0) { - va_next = (sva + L1_SIZE) & ~L1_OFFSET; - if (va_next < sva) - va_next = eva; + if (pmap_load(l1) == 0) + continue; + if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { + KASSERT(va_next <= eva, + ("partial update of non-transparent 1G page " + "l1 %#lx sva %#lx eva %#lx va_next %#lx", + pmap_load(l1), sva, eva, va_next)); + MPASS(pmap != kernel_pmap); + MPASS((pmap_load(l1) & ATTR_SW_MANAGED) == 0); + pmap_clear(l1); + pmap_invalidate_page(pmap, sva); + pmap_resident_count_dec(pmap, L1_SIZE / PAGE_SIZE); + pmap_unuse_pt(pmap, sva, pmap_load(l0), &free); continue; } @@ -3217,11 +3234,22 @@ continue; } + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; l1 = pmap_l0_to_l1(l0, sva); - if (pmap_load(l1) == 0) { - va_next = (sva + L1_SIZE) & ~L1_OFFSET; - if (va_next < sva) - va_next = eva; + if (pmap_load(l1) == 0) + continue; + if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { + KASSERT(va_next <= eva, + ("partial update of non-transparent 1G page " + "l1 %#lx sva %#lx eva %#lx va_next %#lx", + pmap_load(l1), sva, eva, va_next)); + MPASS((pmap_load(l1) & ATTR_SW_MANAGED) == 0); + if ((pmap_load(l1) & mask) != nbits) { + pmap_store(l1, (pmap_load(l1) & ~mask) | nbits); + pmap_invalidate_page(pmap, sva); + } continue; } @@ -3485,6 +3513,96 @@ } #endif /* VM_NRESERVLEVEL > 0 */ +static int +pmap_enter_largepage(pmap_t pmap, vm_offset_t va, pt_entry_t newpte, int flags, + int psind) +{ + pd_entry_t *l0p, *l1p, *l2p, origpte; + vm_page_t mp; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT(psind > 0 && psind < MAXPAGESIZES, + ("psind %d unexpected", psind)); + KASSERT(((newpte & ~ATTR_MASK) & (pagesizes[psind] - 1)) == 0, + ("unaligned phys address %#lx newpte %#lx psind %d", + (newpte & ~ATTR_MASK), newpte, psind)); + +restart: + if (psind == 2) { + l0p = pmap_l0(pmap, va); + if ((pmap_load(l0p) & ATTR_DESCR_VALID) == 0) { + mp = _pmap_alloc_l3(pmap, pmap_l0_pindex(va), NULL); + if (mp == NULL) { + if ((flags & PMAP_ENTER_NOSLEEP) != 0) + return (KERN_RESOURCE_SHORTAGE); + PMAP_UNLOCK(pmap); + vm_wait(NULL); + PMAP_LOCK(pmap); + goto restart; + } + l1p = pmap_l0_to_l1(l0p, va); + KASSERT(l1p != NULL, ("va %#lx lost l1 entry", va)); + origpte = pmap_load(l1p); + } else { + l1p = pmap_l0_to_l1(l0p, va); + KASSERT(l1p != NULL, ("va %#lx lost l1 entry", va)); + origpte = pmap_load(l1p); + if ((origpte & ATTR_DESCR_VALID) == 0) { + mp = PHYS_TO_VM_PAGE(pmap_load(l0p) & + ~ATTR_MASK); + mp->ref_count++; + } + } + KASSERT((origpte & ATTR_DESCR_VALID) == 0 || + ((origpte & ATTR_DESCR_MASK) == L1_BLOCK && + (origpte & ~ATTR_MASK) == (newpte & ~ATTR_MASK)), + ("va %#lx changing 1G phys page l1 %#lx newpte %#lx", + va, origpte, newpte)); + pmap_store(l1p, newpte); + } else /* (psind == 1) */ { + l2p = pmap_l2(pmap, va); + if (l2p == NULL) { + mp = _pmap_alloc_l3(pmap, pmap_l1_pindex(va), NULL); + if (mp == NULL) { + if ((flags & PMAP_ENTER_NOSLEEP) != 0) + return (KERN_RESOURCE_SHORTAGE); + PMAP_UNLOCK(pmap); + vm_wait(NULL); + PMAP_LOCK(pmap); + goto restart; + } + l2p = (pd_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mp)); + l2p = &l2p[pmap_l2_index(va)]; + origpte = pmap_load(l2p); + } else { + l1p = pmap_l1(pmap, va); + origpte = pmap_load(l2p); + if ((origpte & ATTR_DESCR_VALID) == 0) { + mp = PHYS_TO_VM_PAGE(pmap_load(l1p) & + ~ATTR_MASK); + mp->ref_count++; + } + } + KASSERT((origpte & ATTR_DESCR_VALID) == 0 || + ((origpte & ATTR_DESCR_MASK) == L2_BLOCK && + (origpte & ~ATTR_MASK) == (newpte & ~ATTR_MASK)), + ("va %#lx changing 2M phys page l2 %#lx newpte %#lx", + va, origpte, newpte)); + pmap_store(l2p, newpte); + } + dsb(ishst); + + if ((origpte & ATTR_DESCR_VALID) == 0) + pmap_resident_count_inc(pmap, pagesizes[psind] / PAGE_SIZE); + if ((newpte & ATTR_SW_WIRED) != 0 && (origpte & ATTR_SW_WIRED) == 0) + pmap->pm_stats.wired_count += pagesizes[psind] / PAGE_SIZE; + else if ((newpte & ATTR_SW_WIRED) == 0 && + (origpte & ATTR_SW_WIRED) != 0) + pmap->pm_stats.wired_count -= pagesizes[psind] / PAGE_SIZE; + + return (KERN_SUCCESS); +} + /* * Insert the given physical page (p) at * the specified virtual address (v) in the @@ -3560,6 +3678,17 @@ lock = NULL; PMAP_LOCK(pmap); + if ((flags & PMAP_ENTER_LARGEPAGE) != 0) { + KASSERT((m->oflags & VPO_UNMANAGED) != 0, + ("managed largepage va %#lx flags %#x", va, flags)); + new_l3 &= ~L3_PAGE; + if (psind == 2) + new_l3 |= L1_BLOCK; + else /* (psind == 1) */ + new_l3 |= L2_BLOCK; + rv = pmap_enter_largepage(pmap, va, new_l3, flags, psind); + goto out; + } if (psind == 1) { /* Assert the required virtual and physical alignment. */ KASSERT((va & L2_OFFSET) == 0, ("pmap_enter: va unaligned")); @@ -4209,10 +4338,22 @@ } l1 = pmap_l0_to_l1(l0, sva); - if (pmap_load(l1) == 0) { - va_next = (sva + L1_SIZE) & ~L1_OFFSET; - if (va_next < sva) - va_next = eva; + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; + if (pmap_load(l1) == 0) + continue; + + if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { + KASSERT(va_next <= eva, + ("partial update of non-transparent 1G page " + "l1 %#lx sva %#lx eva %#lx va_next %#lx", + pmap_load(l1), sva, eva, va_next)); + MPASS(pmap != kernel_pmap); + MPASS((pmap_load(l1) & (ATTR_SW_MANAGED | + ATTR_SW_WIRED)) == ATTR_SW_WIRED); + pmap_clear_bits(l1, ATTR_SW_WIRED); + pmap->pm_stats.wired_count -= L1_SIZE / PAGE_SIZE; continue; } @@ -4284,7 +4425,7 @@ pd_entry_t *l0, *l1, *l2, srcptepaddr; pt_entry_t *dst_pte, mask, nbits, ptetemp, *src_pte; vm_offset_t addr, end_addr, va_next; - vm_page_t dst_l2pg, dstmpte, srcmpte; + vm_page_t dst_m, dstmpte, srcmpte; PMAP_ASSERT_STAGE1(dst_pmap); PMAP_ASSERT_STAGE1(src_pmap); @@ -4308,13 +4449,40 @@ va_next = end_addr; continue; } + + va_next = (addr + L1_SIZE) & ~L1_OFFSET; + if (va_next < addr) + va_next = end_addr; l1 = pmap_l0_to_l1(l0, addr); - if (pmap_load(l1) == 0) { - va_next = (addr + L1_SIZE) & ~L1_OFFSET; - if (va_next < addr) - va_next = end_addr; + if (pmap_load(l1) == 0) + continue; + if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { + KASSERT(va_next <= end_addr, + ("partial update of non-transparent 1G page " + "l1 %#lx addr %#lx end_addr %#lx va_next %#lx", + pmap_load(l1), addr, end_addr, va_next)); + srcptepaddr = pmap_load(l1); + l1 = pmap_l1(dst_pmap, addr); + if (l1 == NULL) { + if (_pmap_alloc_l3(dst_pmap, + pmap_l0_pindex(addr), NULL) == NULL) + break; + l1 = pmap_l1(dst_pmap, addr); + } else { + l0 = pmap_l0(dst_pmap, addr); + dst_m = PHYS_TO_VM_PAGE(pmap_load(l0) & + ~ATTR_MASK); + dst_m->ref_count++; + } + KASSERT(pmap_load(l1) == 0, + ("1G mapping present in dst pmap " + "l1 %#lx addr %#lx end_addr %#lx va_next %#lx", + pmap_load(l1), addr, end_addr, va_next)); + pmap_store(l1, srcptepaddr & ~ATTR_SW_WIRED); + pmap_resident_count_inc(dst_pmap, L1_SIZE / PAGE_SIZE); continue; } + va_next = (addr + L2_SIZE) & ~L2_OFFSET; if (va_next < addr) va_next = end_addr; @@ -4326,7 +4494,7 @@ if ((addr & L2_OFFSET) != 0 || addr + L2_SIZE > end_addr) continue; - l2 = pmap_alloc_l2(dst_pmap, addr, &dst_l2pg, NULL); + l2 = pmap_alloc_l2(dst_pmap, addr, &dst_m, NULL); if (l2 == NULL) break; if (pmap_load(l2) == 0 && @@ -4342,7 +4510,7 @@ PAGE_SIZE); atomic_add_long(&pmap_l2_mappings, 1); } else - pmap_abort_ptp(dst_pmap, addr, dst_l2pg); + pmap_abort_ptp(dst_pmap, addr, dst_m); continue; } KASSERT((srcptepaddr & ATTR_DESCR_MASK) == L2_TABLE, @@ -5247,13 +5415,21 @@ va_next = eva; continue; } + + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; l1 = pmap_l0_to_l1(l0, sva); - if (pmap_load(l1) == 0) { - va_next = (sva + L1_SIZE) & ~L1_OFFSET; - if (va_next < sva) - va_next = eva; + if (pmap_load(l1) == 0) + continue; + if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { + KASSERT(va_next <= eva, + ("partial update of non-transparent 1G page " + "l1 %#lx sva %#lx eva %#lx va_next %#lx", + pmap_load(l1), sva, eva, va_next)); continue; } + va_next = (sva + L2_SIZE) & ~L2_OFFSET; if (va_next < sva) va_next = eva; Index: sys/arm64/include/param.h =================================================================== --- sys/arm64/include/param.h +++ sys/arm64/include/param.h @@ -95,7 +95,7 @@ #define PAGE_SIZE_64K (1 << PAGE_SHIFT_64K) #define PAGE_MASK_64K (PAGE_SIZE_64K - 1) -#define MAXPAGESIZES 2 /* maximum number of supported page sizes */ +#define MAXPAGESIZES 3 /* maximum number of supported page sizes */ #ifndef KSTACK_PAGES #define KSTACK_PAGES 4 /* pages of kernel stack (with pcb) */ Index: sys/arm64/include/vmparam.h =================================================================== --- sys/arm64/include/vmparam.h +++ sys/arm64/include/vmparam.h @@ -243,6 +243,11 @@ #define DEVMAP_MAX_VADDR VM_MAX_KERNEL_ADDRESS +/* + * The pmap can create non-transparent large page mappings. + */ +#define PMAP_HAS_LARGEPAGES 1 + /* * Need a page dump array for minidump. */ Index: sys/compat/cloudabi/cloudabi_proc.c =================================================================== --- sys/compat/cloudabi/cloudabi_proc.c +++ sys/compat/cloudabi/cloudabi_proc.c @@ -57,7 +57,7 @@ uap->fds, uap->fds_len); if (error == 0) { args.fd = uap->fd; - error = kern_execve(td, &args, NULL); + error = kern_execve(td, &args, NULL, oldvmspace); } post_execve(td, error, oldvmspace); return (error); Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c +++ sys/compat/freebsd32/freebsd32_misc.c @@ -440,7 +440,7 @@ error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, uap->argv, uap->envv); if (error == 0) - error = kern_execve(td, &eargs, NULL); + error = kern_execve(td, &eargs, NULL, oldvmspace); post_execve(td, error, oldvmspace); return (error); } @@ -459,7 +459,7 @@ uap->argv, uap->envv); if (error == 0) { eargs.fd = uap->fd; - error = kern_execve(td, &eargs, NULL); + error = kern_execve(td, &eargs, NULL, oldvmspace); } post_execve(td, error, oldvmspace); return (error); Index: sys/compat/linux/linux_emul.c =================================================================== --- sys/compat/linux/linux_emul.c +++ sys/compat/linux/linux_emul.c @@ -256,7 +256,7 @@ if (error != 0) return (error); - error = kern_execve(td, eargs, NULL); + error = kern_execve(td, eargs, NULL, oldvmspace); post_execve(td, error, oldvmspace); if (error != EJUSTRETURN) return (error); Index: sys/conf/NOTES =================================================================== --- sys/conf/NOTES +++ sys/conf/NOTES @@ -6,8 +6,8 @@ # 'makeoptions', 'hints', etc. go into the kernel configuration that you # run config(8) with. # -# Lines that begin with 'hint.' are NOT for config(8), they go into your -# hints file. See /boot/device.hints and/or the 'hints' config(8) directive. +# Lines that begin with 'envvar hint.' should go into your hints file. +# See /boot/device.hints and/or the 'hints' config(8) directive. # # Please use ``make LINT'' to create an old-style LINT file if you want to # do kernel test-builds. @@ -1292,22 +1292,22 @@ # The syntax for wiring down devices is: -hint.scbus.0.at="ahc0" -hint.scbus.1.at="ahc1" -hint.scbus.1.bus="0" -hint.scbus.3.at="ahc2" -hint.scbus.3.bus="0" -hint.scbus.2.at="ahc2" -hint.scbus.2.bus="1" -hint.da.0.at="scbus0" -hint.da.0.target="0" -hint.da.0.unit="0" -hint.da.1.at="scbus3" -hint.da.1.target="1" -hint.da.2.at="scbus2" -hint.da.2.target="3" -hint.sa.1.at="scbus1" -hint.sa.1.target="6" +envvar hint.scbus.0.at="ahc0" +envvar hint.scbus.1.at="ahc1" +envvar hint.scbus.1.bus="0" +envvar hint.scbus.3.at="ahc2" +envvar hint.scbus.3.bus="0" +envvar hint.scbus.2.at="ahc2" +envvar hint.scbus.2.bus="1" +envvar hint.da.0.at="scbus0" +envvar hint.da.0.target="0" +envvar hint.da.0.unit="0" +envvar hint.da.1.at="scbus3" +envvar hint.da.1.target="1" +envvar hint.da.2.at="scbus2" +envvar hint.da.2.target="3" +envvar hint.sa.1.at="scbus1" +envvar hint.sa.1.target="6" # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. @@ -1536,21 +1536,21 @@ device esp device iscsi_initiator device isp -hint.isp.0.disable="1" -hint.isp.0.role="3" -hint.isp.0.prefer_iomap="1" -hint.isp.0.prefer_memmap="1" -hint.isp.0.fwload_disable="1" -hint.isp.0.ignore_nvram="1" -hint.isp.0.fullduplex="1" -hint.isp.0.topology="lport" -hint.isp.0.topology="nport" -hint.isp.0.topology="lport-only" -hint.isp.0.topology="nport-only" +envvar hint.isp.0.disable="1" +envvar hint.isp.0.role="3" +envvar hint.isp.0.prefer_iomap="1" +envvar hint.isp.0.prefer_memmap="1" +envvar hint.isp.0.fwload_disable="1" +envvar hint.isp.0.ignore_nvram="1" +envvar hint.isp.0.fullduplex="1" +envvar hint.isp.0.topology="lport" +envvar hint.isp.0.topology="nport" +envvar hint.isp.0.topology="lport-only" +envvar hint.isp.0.topology="nport-only" # we can't get u_int64_t types, nor can we get strings if it's got # a leading 0x, hence this silly dodge. -hint.isp.0.portwnn="w50000000aaaa0000" -hint.isp.0.nodewnn="w50000000aaaa0001" +envvar hint.isp.0.portwnn="w50000000aaaa0000" +envvar hint.isp.0.nodewnn="w50000000aaaa0001" device ispfw device mpr # LSI-Logic MPT-Fusion 3 device mps # LSI-Logic MPT-Fusion 2 @@ -1715,12 +1715,12 @@ # # For older non-PCI, non-PnPBIOS systems, these are the hints lines to add: -hint.ata.0.at="isa" -hint.ata.0.port="0x1f0" -hint.ata.0.irq="14" -hint.ata.1.at="isa" -hint.ata.1.port="0x170" -hint.ata.1.irq="15" +envvar hint.ata.0.at="isa" +envvar hint.ata.0.port="0x1f0" +envvar hint.ata.0.irq="14" +envvar hint.ata.1.at="isa" +envvar hint.ata.1.port="0x170" +envvar hint.ata.1.irq="15" # # uart: newbusified driver for serial interfaces. It consolidates the sio(4), @@ -1736,16 +1736,16 @@ # The following hint should only be used for pure ISA devices. It is not # needed otherwise. Use of hints is strongly discouraged. -hint.uart.0.at="isa" +envvar hint.uart.0.at="isa" # The following 3 hints are used when the UART is a system device (i.e., a # console or debug port), but only on platforms that don't have any other # means to pass the information to the kernel. The unit number of the hint # is only used to bundle the hints together. There is no relation to the # unit number of the probed UART. -hint.uart.0.port="0x3f8" -hint.uart.0.flags="0x10" -hint.uart.0.baud="115200" +envvar hint.uart.0.port="0x3f8" +envvar hint.uart.0.flags="0x10" +envvar hint.uart.0.baud="115200" # `flags' for serial drivers that support consoles like sio(4) and uart(4): # 0x10 enable console support for this unit. Other console flags @@ -1954,7 +1954,7 @@ device dc # DEC/Intel 21143 and various workalikes device et # Agere ET1310 10/100/Gigabit Ethernet device fxp # Intel EtherExpress PRO/100B (82557, 82558) -hint.fxp.0.prefer_iomap="0" +envvar hint.fxp.0.prefer_iomap="0" device gem # Apple GMAC/Sun ERI/Sun GEM device hme # Sun HME (Happy Meal Ethernet) device jme # JMicron JMC250 Gigabit/JMC260 Fast Ethernet @@ -2138,20 +2138,20 @@ device snd_vibes # For non-PnP sound cards: -hint.pcm.0.at="isa" -hint.pcm.0.irq="10" -hint.pcm.0.drq="1" -hint.pcm.0.flags="0x0" -hint.sbc.0.at="isa" -hint.sbc.0.port="0x220" -hint.sbc.0.irq="5" -hint.sbc.0.drq="1" -hint.sbc.0.flags="0x15" -hint.gusc.0.at="isa" -hint.gusc.0.port="0x220" -hint.gusc.0.irq="5" -hint.gusc.0.drq="1" -hint.gusc.0.flags="0x13" +envvar hint.pcm.0.at="isa" +envvar hint.pcm.0.irq="10" +envvar hint.pcm.0.drq="1" +envvar hint.pcm.0.flags="0x0" +envvar hint.sbc.0.at="isa" +envvar hint.sbc.0.port="0x220" +envvar hint.sbc.0.irq="5" +envvar hint.sbc.0.drq="1" +envvar hint.sbc.0.flags="0x15" +envvar hint.gusc.0.at="isa" +envvar hint.gusc.0.port="0x220" +envvar hint.gusc.0.irq="5" +envvar hint.gusc.0.drq="1" +envvar hint.gusc.0.flags="0x13" # # Following options are intended for debugging/testing purposes: @@ -2333,8 +2333,8 @@ options PCFCLOCK_MAX_RETRIES=5 # Maximum read tries (default 10) device ppc -hint.ppc.0.at="isa" -hint.ppc.0.irq="7" +envvar hint.ppc.0.at="isa" +envvar hint.ppc.0.irq="7" device ppbus device lpt device plip Index: sys/conf/makeLINT.mk =================================================================== --- sys/conf/makeLINT.mk +++ sys/conf/makeLINT.mk @@ -11,12 +11,6 @@ .if ${TARGET} == "amd64" || ${TARGET} == "i386" rm -f LINT-NOINET LINT-NOINET6 LINT-NOIP .endif -.if ${TARGET} == "arm" - # LINT-V5 removed 2019-11-26. The clean rule is left here temporarily - # to avoid having stale copies left behind. LINT-V7 left the tree on - # 2020-02-02. - rm -f LINT-V5 LINT-V7 -.endif .if ${TARGET} == "powerpc" rm -f LINT64 .endif Index: sys/i386/conf/NOTES =================================================================== --- sys/i386/conf/NOTES +++ sys/i386/conf/NOTES @@ -273,8 +273,8 @@ # MISCELLANEOUS DEVICES AND OPTIONS device speaker #Play IBM BASIC-style noises out your speaker -hint.speaker.0.at="isa" -hint.speaker.0.port="0x61" +envvar hint.speaker.0.at="isa" +envvar hint.speaker.0.port="0x61" device apm_saver # Requires APM @@ -342,8 +342,8 @@ # # Hints for the non-optional Numeric Processing eXtension driver. -hint.npx.0.flags="0x0" -hint.npx.0.irq="13" +envvar hint.npx.0.flags="0x0" +envvar hint.npx.0.irq="13" # # `flags' for npx0: @@ -369,8 +369,8 @@ # PS/2 mouse device psm -hint.psm.0.at="atkbdc" -hint.psm.0.irq="12" +envvar hint.psm.0.at="atkbdc" +envvar hint.psm.0.irq="12" # Options for psm: options PSM_HOOKRESUME #hook the system resume event, useful @@ -379,13 +379,13 @@ # The keyboard controller; it controls the keyboard and the PS/2 mouse. device atkbdc -hint.atkbdc.0.at="isa" -hint.atkbdc.0.port="0x060" +envvar hint.atkbdc.0.at="isa" +envvar hint.atkbdc.0.port="0x060" # The AT keyboard device atkbd -hint.atkbd.0.at="atkbdc" -hint.atkbd.0.irq="1" +envvar hint.atkbd.0.at="atkbdc" +envvar hint.atkbd.0.irq="1" # Options for atkbd: options ATKBD_DFLT_KEYMAP # specify the built-in keymap @@ -400,7 +400,7 @@ # Video card driver for VGA adapters. device vga -hint.vga.0.at="isa" +envvar hint.vga.0.at="isa" # Options for vga: # Try the following option if the mouse pointer is not drawn correctly @@ -521,34 +521,34 @@ device bxe # Broadcom NetXtreme II BCM5771X/BCM578XX 10GbE device ce device cp -hint.cs.0.at="isa" -hint.cs.0.port="0x300" +envvar hint.cs.0.at="isa" +envvar hint.cs.0.port="0x300" #options NETGRAPH_CRONYX # Enable NETGRAPH support for Cronyx adapter(s) options ED_3C503 options ED_HPP options ED_SIC -hint.ed.0.at="isa" -hint.ed.0.port="0x280" -hint.ed.0.irq="5" -hint.ed.0.maddr="0xd8000" +envvar hint.ed.0.at="isa" +envvar hint.ed.0.port="0x280" +envvar hint.ed.0.irq="5" +envvar hint.ed.0.maddr="0xd8000" device ipw # Intel 2100 wireless NICs. device iwi # Intel 2200BG/2225BG/2915ABG wireless NICs. device iwn # Intel 4965/1000/5000/6000 wireless NICs. # Hint for the i386-only ISA front-end of le(4). -hint.le.0.at="isa" -hint.le.0.port="0x280" -hint.le.0.irq="10" -hint.le.0.drq="0" +envvar hint.le.0.at="isa" +envvar hint.le.0.port="0x280" +envvar hint.le.0.irq="10" +envvar hint.le.0.drq="0" device mthca # Mellanox HCA InfiniBand device mlx4 # Shared code module between IB and Ethernet device mlx4ib # Mellanox ConnectX HCA InfiniBand device mlx4en # Mellanox ConnectX HCA Ethernet device nfe # nVidia nForce MCP on-board Ethernet device sbni -hint.sbni.0.at="isa" -hint.sbni.0.port="0x210" -hint.sbni.0.irq="0xefdead" -hint.sbni.0.flags="0" +envvar hint.sbni.0.at="isa" +envvar hint.sbni.0.port="0x210" +envvar hint.sbni.0.irq="0xefdead" +envvar hint.sbni.0.flags="0" device vmx # VMware VMXNET3 Ethernet device wpi # Intel 3945ABG wireless NICs. @@ -762,14 +762,14 @@ # of the Vaio extra features are controlled by this device. device apm -hint.apm.0.flags="0x20" +envvar hint.apm.0.flags="0x20" device ipmi device smapi device smbios device vpd device pbio -hint.pbio.0.at="isa" -hint.pbio.0.port="0x360" +envvar hint.pbio.0.at="isa" +envvar hint.pbio.0.port="0x360" device asmc device tpm device padlock_rng # VIA Padlock RNG @@ -797,9 +797,9 @@ # pcf Philips PCF8584 ISA-bus controller # device pcf -hint.pcf.0.at="isa" -hint.pcf.0.port="0x320" -hint.pcf.0.irq="5" +envvar hint.pcf.0.at="isa" +envvar hint.pcf.0.port="0x320" +envvar hint.pcf.0.irq="5" # # Hardware watchdog timers: Index: sys/i386/include/vmparam.h =================================================================== --- sys/i386/include/vmparam.h +++ sys/i386/include/vmparam.h @@ -240,6 +240,11 @@ #define PHYS_TO_DMAP(x) ({ panic("No direct map exists"); 0; }) #define DMAP_TO_PHYS(x) ({ panic("No direct map exists"); 0; }) +/* + * No non-transparent large page support in the pmap. + */ +#define PMAP_HAS_LARGEPAGES 0 + /* * Need a page dump array for minidump. */ Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c +++ sys/kern/init_main.c @@ -752,16 +752,11 @@ KASSERT((td->td_pflags & TDP_EXECVMSPC) == 0, ("nested execve")); oldvmspace = td->td_proc->p_vmspace; - error = kern_execve(td, &args, NULL); + error = kern_execve(td, &args, NULL, oldvmspace); KASSERT(error != 0, ("kern_execve returned success, not EJUSTRETURN")); if (error == EJUSTRETURN) { - if ((td->td_pflags & TDP_EXECVMSPC) != 0) { - KASSERT(p->p_vmspace != oldvmspace, - ("oldvmspace still used")); - vmspace_free(oldvmspace); - td->td_pflags &= ~TDP_EXECVMSPC; - } + exec_cleanup(td, oldvmspace); free(free_init_path, M_TEMP); TSEXIT(); return; Index: sys/kern/kern_exec.c =================================================================== --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -118,7 +118,7 @@ static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS); static int do_execve(struct thread *td, struct image_args *args, - struct mac *mac_p); + struct mac *mac_p, struct vmspace *oldvmspace); /* XXX This should be vm_size_t. */ SYSCTL_PROC(_kern, KERN_PS_STRINGS, ps_strings, CTLTYPE_ULONG|CTLFLAG_RD| @@ -223,7 +223,7 @@ error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, uap->argv, uap->envv); if (error == 0) - error = kern_execve(td, &args, NULL); + error = kern_execve(td, &args, NULL, oldvmspace); post_execve(td, error, oldvmspace); return (error); } @@ -249,7 +249,7 @@ uap->argv, uap->envv); if (error == 0) { args.fd = uap->fd; - error = kern_execve(td, &args, NULL); + error = kern_execve(td, &args, NULL, oldvmspace); } post_execve(td, error, oldvmspace); return (error); @@ -278,7 +278,7 @@ error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, uap->argv, uap->envv); if (error == 0) - error = kern_execve(td, &args, uap->mac_p); + error = kern_execve(td, &args, uap->mac_p, oldvmspace); post_execve(td, error, oldvmspace); return (error); #else @@ -326,30 +326,26 @@ thread_single_end(p, SINGLE_BOUNDARY); PROC_UNLOCK(p); } - if ((td->td_pflags & TDP_EXECVMSPC) != 0) { - KASSERT(p->p_vmspace != oldvmspace, - ("oldvmspace still used")); - vmspace_free(oldvmspace); - td->td_pflags &= ~TDP_EXECVMSPC; - } + exec_cleanup(td, oldvmspace); } /* - * XXX: kern_execve has the astonishing property of not always returning to + * kern_execve() has the astonishing property of not always returning to * the caller. If sufficiently bad things happen during the call to * do_execve(), it can end up calling exit1(); as a result, callers must * avoid doing anything which they might need to undo (e.g., allocating * memory). */ int -kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p) +kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p, + struct vmspace *oldvmspace) { AUDIT_ARG_ARGV(args->begin_argv, args->argc, exec_args_get_begin_envv(args) - args->begin_argv); AUDIT_ARG_ENVV(exec_args_get_begin_envv(args), args->envc, args->endp - exec_args_get_begin_envv(args)); - return (do_execve(td, args, mac_p)); + return (do_execve(td, args, mac_p, oldvmspace)); } /* @@ -357,7 +353,8 @@ * userspace pointers from the passed thread. */ static int -do_execve(struct thread *td, struct image_args *args, struct mac *mac_p) +do_execve(struct thread *td, struct image_args *args, struct mac *mac_p, + struct vmspace *oldvmspace) { struct proc *p = td->td_proc; struct nameidata nd; @@ -949,6 +946,7 @@ if (error && imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ + exec_cleanup(td, oldvmspace); exit1(td, 0, SIGABRT); /* NOT REACHED */ } @@ -967,6 +965,20 @@ return (error == 0 ? EJUSTRETURN : error); } +void +exec_cleanup(struct thread *td, struct vmspace *oldvmspace) +{ + struct proc *p; + + p = td->td_proc; + if ((td->td_pflags & TDP_EXECVMSPC) != 0) { + KASSERT(p->p_vmspace != oldvmspace, + ("oldvmspace still used")); + vmspace_free(oldvmspace); + td->td_pflags &= ~TDP_EXECVMSPC; + } +} + int exec_map_first_page(struct image_params *imgp) { Index: sys/kern/uipc_shm.c =================================================================== --- sys/kern/uipc_shm.c +++ sys/kern/uipc_shm.c @@ -1067,10 +1067,8 @@ return (EINVAL); largepage = (shmflags & SHM_LARGEPAGE) != 0; -#if !defined(__amd64__) - if (largepage) + if (largepage && !PMAP_HAS_LARGEPAGES) return (ENOTTY); -#endif /* * Currently only F_SEAL_SEAL may be set when creating or opening shmfd. Index: sys/kern/vfs_cache.c =================================================================== --- sys/kern/vfs_cache.c +++ sys/kern/vfs_cache.c @@ -1089,52 +1089,6 @@ return (false); } -static int __noinline -cache_zap_locked_vnode(struct namecache *ncp, struct vnode *vp) -{ - struct mtx *pvlp, *vlp1, *vlp2, *to_unlock; - struct mtx *blp; - int error = 0; - - MPASS(vp == ncp->nc_dvp || vp == ncp->nc_vp); - cache_assert_vnode_locked(vp); - - pvlp = VP2VNODELOCK(vp); - if (ncp->nc_flag & NCF_NEGATIVE) { - cache_zap_negative_locked_vnode_kl(ncp, vp); - goto out; - } - - blp = NCP2BUCKETLOCK(ncp); - vlp1 = VP2VNODELOCK(ncp->nc_dvp); - vlp2 = VP2VNODELOCK(ncp->nc_vp); - cache_sort_vnodes(&vlp1, &vlp2); - if (vlp1 == pvlp) { - mtx_lock(vlp2); - to_unlock = vlp2; - } else { - if (!mtx_trylock(vlp1)) { - /* - * TODO: Very wasteful but rare. - */ - mtx_unlock(pvlp); - mtx_lock(vlp1); - mtx_lock(vlp2); - mtx_unlock(vlp2); - mtx_unlock(vlp1); - return (EAGAIN); - } - to_unlock = vlp1; - } - mtx_lock(blp); - cache_zap_locked(ncp); - mtx_unlock(blp); - mtx_unlock(to_unlock); -out: - mtx_unlock(pvlp); - return (error); -} - /* * If trylocking failed we can get here. We know enough to take all needed locks * in the right order and re-lookup the entry. @@ -1373,11 +1327,8 @@ if (__predict_false(cnp->cn_nameiop == CREATE)) { if (cnp->cn_flags & ISLASTCN) { counter_u64_add(numnegzaps, 1); - error = cache_zap_locked_vnode(ncp, dvp); - if (__predict_false(error != 0)) { - zap_and_exit_bucket_fail2++; - goto retry; - } + cache_zap_negative_locked_vnode_kl(ncp, dvp); + mtx_unlock(dvlp); cache_free(ncp); return (0); } @@ -1484,7 +1435,7 @@ if (__predict_false(cnp->cn_nameiop == CREATE)) { if (cnp->cn_flags & ISLASTCN) { counter_u64_add(numnegzaps, 1); - error = cache_zap_locked_vnode(ncp, dvp); + error = cache_zap_locked_bucket(ncp, cnp, hash, blp); if (__predict_false(error != 0)) { zap_and_exit_bucket_fail2++; goto retry; Index: sys/mips/include/vmparam.h =================================================================== --- sys/mips/include/vmparam.h +++ sys/mips/include/vmparam.h @@ -197,6 +197,11 @@ #define PHYS_TO_DMAP(x) MIPS_PHYS_TO_DIRECT(x) #define DMAP_TO_PHYS(x) MIPS_DIRECT_TO_PHYS(x) +/* + * No non-transparent large page support in the pmap. + */ +#define PMAP_HAS_LARGEPAGES 0 + /* * Need a page dump array for minidump. */ Index: sys/modules/mrsas/Makefile =================================================================== --- sys/modules/mrsas/Makefile +++ sys/modules/mrsas/Makefile @@ -17,7 +17,7 @@ TARGET_ARCH = ${MACHINE_ARCH} .if ${TARGET_ARCH} == "amd64" -CFLAGS+= -DCOMPAT_FREEBSD32 -D_STANDALONE +CFLAGS+= -DCOMPAT_FREEBSD32 .endif clean_cscope: Index: sys/powerpc/include/vmparam.h =================================================================== --- sys/powerpc/include/vmparam.h +++ sys/powerpc/include/vmparam.h @@ -327,4 +327,9 @@ KASSERT(hw_direct_map, ("Direct map not provided by PMAP")); \ (x) &~ DMAP_BASE_ADDRESS; }) +/* + * No non-transparent large page support in the pmap. + */ +#define PMAP_HAS_LARGEPAGES 0 + #endif /* _MACHINE_VMPARAM_H_ */ Index: sys/riscv/include/vmparam.h =================================================================== --- sys/riscv/include/vmparam.h +++ sys/riscv/include/vmparam.h @@ -236,6 +236,11 @@ #define DEVMAP_MAX_VADDR VM_MAX_KERNEL_ADDRESS +/* + * No non-transparent large page support in the pmap. + */ +#define PMAP_HAS_LARGEPAGES 0 + /* * Need a page dump array for minidump. */ Index: sys/riscv/riscv/trap.c =================================================================== --- sys/riscv/riscv/trap.c +++ sys/riscv/riscv/trap.c @@ -136,15 +136,15 @@ int n; int i; - n = (sizeof(frame->tf_t) / sizeof(frame->tf_t[0])); + n = nitems(frame->tf_t); for (i = 0; i < n; i++) printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]); - n = (sizeof(frame->tf_s) / sizeof(frame->tf_s[0])); + n = nitems(frame->tf_s); for (i = 0; i < n; i++) printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]); - n = (sizeof(frame->tf_a) / sizeof(frame->tf_a[0])); + n = nitems(frame->tf_a); for (i = 0; i < n; i++) printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]); @@ -283,6 +283,9 @@ case EXCP_FAULT_LOAD: case EXCP_FAULT_STORE: case EXCP_FAULT_FETCH: + dump_regs(frame); + panic("Memory access exception at 0x%016lx\n", frame->tf_sepc); + break; case EXCP_STORE_PAGE_FAULT: case EXCP_LOAD_PAGE_FAULT: data_abort(frame, 0); Index: sys/sys/imgact.h =================================================================== --- sys/sys/imgact.h +++ sys/sys/imgact.h @@ -112,6 +112,7 @@ ssize_t extend); char *exec_args_get_begin_envv(struct image_args *args); int exec_check_permissions(struct image_params *); +void exec_cleanup(struct thread *td, struct vmspace *); int exec_copyout_strings(struct image_params *, uintptr_t *); void exec_free_args(struct image_args *); int exec_new_vmspace(struct image_params *, struct sysentvec *); Index: sys/sys/malloc.h =================================================================== --- sys/sys/malloc.h +++ sys/sys/malloc.h @@ -37,6 +37,7 @@ #ifndef _SYS_MALLOC_H_ #define _SYS_MALLOC_H_ +#ifndef _STANDALONE #include #ifdef _KERNEL #include @@ -267,4 +268,34 @@ #undef MUL_NO_OVERFLOW #endif /* _KERNEL */ +#else +/* + * The native stand malloc / free interface we're mapping to + */ +extern void Free(void *p, const char *file, int line); +extern void *Malloc(size_t bytes, const char *file, int line); + +/* + * Minimal standalone malloc implementation / environment. None of the + * flags mean anything and there's no need declare malloc types. + * Define the simple alloc / free routines in terms of Malloc and + * Free. None of the kernel features that this stuff disables are needed. + * + * XXX we are setting ourselves up for a potential crash if we can't allocate + * memory for a M_WAITOK call. + */ +#define M_WAITOK 0 +#define M_ZERO 0 +#define M_NOWAIT 0 +#define MALLOC_DECLARE(x) + +#define kmem_zalloc(size, flags) Malloc((size), __FILE__, __LINE__) +#define kmem_free(p, size) Free(p, __FILE__, __LINE__) + +/* + * ZFS mem.h define that's the OpenZFS porting layer way of saying + * M_WAITOK. Given the above, it will also be a nop. + */ +#define KM_SLEEP M_WAITOK +#endif /* _STANDALONE */ #endif /* !_SYS_MALLOC_H_ */ Index: sys/sys/syscallsubr.h =================================================================== --- sys/sys/syscallsubr.h +++ sys/sys/syscallsubr.h @@ -63,6 +63,7 @@ struct thr_param; struct uio; struct vm_map; +struct vmspace; typedef int (*mmap_check_fp_fn)(struct file *, int, int, int); @@ -129,7 +130,7 @@ id_t id, cpusetid_t setid); int kern_dup(struct thread *td, u_int mode, int flags, int old, int new); int kern_execve(struct thread *td, struct image_args *args, - struct mac *mac_p); + struct mac *mac_p, struct vmspace *oldvmspace); int kern_fchmodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, mode_t mode, int flag); int kern_fchownat(struct thread *td, int fd, const char *path, Index: sys/vm/vm_fault.c =================================================================== --- sys/vm/vm_fault.c +++ sys/vm/vm_fault.c @@ -487,6 +487,8 @@ * populate only busies the first page in superpage run. */ if (bdry_idx != 0) { + KASSERT(PMAP_HAS_LARGEPAGES, + ("missing pmap support for large pages")); m = vm_page_lookup(fs->first_object, pager_first); vm_fault_populate_check_page(m); VM_OBJECT_WUNLOCK(fs->first_object); Index: sys/vm/vm_phys.c =================================================================== --- sys/vm/vm_phys.c +++ sys/vm/vm_phys.c @@ -151,20 +151,20 @@ static int sysctl_vm_phys_free(SYSCTL_HANDLER_ARGS); SYSCTL_OID(_vm, OID_AUTO, phys_free, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, NULL, 0, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_phys_free, "A", "Phys Free Info"); static int sysctl_vm_phys_segs(SYSCTL_HANDLER_ARGS); SYSCTL_OID(_vm, OID_AUTO, phys_segs, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, NULL, 0, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_phys_segs, "A", "Phys Seg Info"); #ifdef NUMA static int sysctl_vm_phys_locality(SYSCTL_HANDLER_ARGS); SYSCTL_OID(_vm, OID_AUTO, phys_locality, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, NULL, 0, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_phys_locality, "A", "Phys Locality Info"); #endif Index: sys/vm/vm_reserv.c =================================================================== --- sys/vm/vm_reserv.c +++ sys/vm/vm_reserv.c @@ -280,7 +280,7 @@ static int sysctl_vm_reserv_partpopq(SYSCTL_HANDLER_ARGS); SYSCTL_OID(_vm_reserv, OID_AUTO, partpopq, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, NULL, 0, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_reserv_partpopq, "A", "Partially populated reservation queues"); Index: sys/x86/conf/NOTES =================================================================== --- sys/x86/conf/NOTES +++ sys/x86/conf/NOTES @@ -18,7 +18,7 @@ # The syscons console driver (SCO color console compatible). device sc -hint.sc.0.at="isa" +envvar hint.sc.0.at="isa" options MAXCONS=16 # number of virtual consoles options SC_ALT_MOUSE_IMAGE # simplified mouse cursor in text mode options SC_DFLT_FONT # compile font in @@ -83,10 +83,10 @@ # the Y-E DATA External FDD (PC Card) # device fdc -hint.fdc.0.at="isa" -hint.fdc.0.port="0x3F0" -hint.fdc.0.irq="6" -hint.fdc.0.drq="2" +envvar hint.fdc.0.at="isa" +envvar hint.fdc.0.port="0x3F0" +envvar hint.fdc.0.irq="6" +envvar hint.fdc.0.drq="2" # # FDC_DEBUG enables floppy debugging. Since the debug output is huge, you # gotta turn it actually on by setting the variable fd_debug with DDB, @@ -99,7 +99,7 @@ #hint.fdc.0.flags="1" # Specify floppy devices -hint.fd.0.at="fdc0" -hint.fd.0.drive="0" -hint.fd.1.at="fdc0" -hint.fd.1.drive="1" +envvar hint.fd.0.at="fdc0" +envvar hint.fd.0.drive="0" +envvar hint.fd.1.at="fdc0" +envvar hint.fd.1.drive="1" Index: tests/sys/kern/Makefile =================================================================== --- tests/sys/kern/Makefile +++ tests/sys/kern/Makefile @@ -11,7 +11,6 @@ ATF_TESTS_C+= kern_copyin ATF_TESTS_C+= kern_descrip_test ATF_TESTS_C+= kill_zombie -ATF_TESTS_C+= memfd_test ATF_TESTS_C+= ptrace_test TEST_METADATA.ptrace_test+= timeout="15" ATF_TESTS_C+= reaper Index: tests/sys/kern/memfd_test.c =================================================================== --- /dev/null +++ tests/sys/kern/memfd_test.c @@ -1,295 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2019 Kyle Evans - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include -#include -#include - -ATF_TC_WITHOUT_HEAD(basic); -ATF_TC_BODY(basic, tc) -{ - struct stat sb; - int fd; - char buf[8]; - - ATF_REQUIRE((fd = memfd_create("...", 0)) != -1); - - /* write(2) should grow us out automatically. */ - ATF_REQUIRE(write(fd, buf, sizeof(buf)) == sizeof(buf)); - ATF_REQUIRE(fstat(fd, &sb) == 0); - ATF_REQUIRE(sb.st_size == sizeof(buf)); - - /* ftruncate(2) must succeed without seals */ - ATF_REQUIRE(ftruncate(fd, 2 * (sizeof(buf) - 1)) == 0); - - /* write(2) again must not be limited by ftruncate(2) size. */ - ATF_REQUIRE(write(fd, buf, sizeof(buf)) == sizeof(buf)); - - /* Sanity check. */ - ATF_REQUIRE(fstat(fd, &sb) == 0); - ATF_REQUIRE(sb.st_size == 2 * sizeof(buf)); - - close(fd); -} - -ATF_TC_WITHOUT_HEAD(cloexec); -ATF_TC_BODY(cloexec, tc) -{ - int fd_nocl, fd_cl; - - ATF_REQUIRE((fd_nocl = memfd_create("...", 0)) != -1); - ATF_REQUIRE((fd_cl = memfd_create("...", MFD_CLOEXEC)) != -1); - - ATF_REQUIRE((fcntl(fd_nocl, F_GETFD) & FD_CLOEXEC) == 0); - ATF_REQUIRE((fcntl(fd_cl, F_GETFD) & FD_CLOEXEC) != 0); - - close(fd_nocl); - close(fd_cl); -} - -ATF_TC_WITHOUT_HEAD(disallowed_sealing); -ATF_TC_BODY(disallowed_sealing, tc) -{ - int fd; - - ATF_REQUIRE((fd = memfd_create("...", 0)) != -1); - ATF_REQUIRE(fcntl(fd, F_GET_SEALS) == F_SEAL_SEAL); - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1); - ATF_REQUIRE(errno == EPERM); - - close(fd); -} - -#define BUF_SIZE 1024 - -ATF_TC_WITHOUT_HEAD(write_seal); -ATF_TC_BODY(write_seal, tc) -{ - int fd; - char *addr, buf[BUF_SIZE]; - - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - ATF_REQUIRE(ftruncate(fd, BUF_SIZE) == 0); - - /* Write once, then we'll seal it and try again */ - ATF_REQUIRE(write(fd, buf, BUF_SIZE) == BUF_SIZE); - ATF_REQUIRE(lseek(fd, 0, SEEK_SET) == 0); - - addr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0); - ATF_REQUIRE(addr != MAP_FAILED); - ATF_REQUIRE(munmap(addr, BUF_SIZE) == 0); - - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == 0); - - ATF_REQUIRE(write(fd, buf, BUF_SIZE) == -1); - ATF_REQUIRE(errno == EPERM); - - ATF_REQUIRE(mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, - fd, 0) == MAP_FAILED); - ATF_REQUIRE(errno == EACCES); - - close(fd); -} - -ATF_TC_WITHOUT_HEAD(mmap_write_seal); -ATF_TC_BODY(mmap_write_seal, tc) -{ - int fd; - char *addr, *paddr, *raddr; - - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - ATF_REQUIRE(ftruncate(fd, BUF_SIZE) == 0); - - /* Map it, both shared and privately */ - addr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0); - ATF_REQUIRE(addr != MAP_FAILED); - paddr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0); - ATF_REQUIRE(paddr != MAP_FAILED); - raddr = mmap(0, BUF_SIZE, PROT_READ, MAP_SHARED, fd, 0); - ATF_REQUIRE(raddr != MAP_FAILED); - - /* Now try to seal it before unmapping */ - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1); - ATF_REQUIRE(errno == EBUSY); - - ATF_REQUIRE(munmap(addr, BUF_SIZE) == 0); - - /* - * This should fail, because raddr still exists and it was spawned from - * a r/w fd. - */ - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1); - ATF_REQUIRE(errno == EBUSY); - - ATF_REQUIRE(munmap(raddr, BUF_SIZE) == 0); - /* This one should succeed; only the private mapping remains. */ - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == 0); - - ATF_REQUIRE(munmap(paddr, BUF_SIZE) == 0); - ATF_REQUIRE(mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, - fd, 0) == MAP_FAILED); - ATF_REQUIRE(errno == EACCES); - - /* Make sure we can still map privately r/w or shared r/o. */ - paddr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0); - ATF_REQUIRE(paddr != MAP_FAILED); - raddr = mmap(0, BUF_SIZE, PROT_READ, MAP_SHARED, fd, 0); - ATF_REQUIRE(raddr != MAP_FAILED); - ATF_REQUIRE(munmap(raddr, BUF_SIZE) == 0); - ATF_REQUIRE(munmap(paddr, BUF_SIZE) == 0); - - close(fd); -} - -static int -memfd_truncate_test(int initial_size, int dest_size, int seals) -{ - int err, fd; - - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - ATF_REQUIRE(ftruncate(fd, initial_size) == 0); - - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, seals) == 0); - - err = ftruncate(fd, dest_size); - if (err != 0) - err = errno; - close(fd); - return (err); -} - -ATF_TC_WITHOUT_HEAD(truncate_seals); -ATF_TC_BODY(truncate_seals, tc) -{ - - ATF_REQUIRE(memfd_truncate_test(4, 8, F_SEAL_GROW) == EPERM); - ATF_REQUIRE(memfd_truncate_test(8, 4, F_SEAL_SHRINK) == EPERM); - ATF_REQUIRE(memfd_truncate_test(8, 4, F_SEAL_GROW) == 0); - ATF_REQUIRE(memfd_truncate_test(4, 8, F_SEAL_SHRINK) == 0); - - ATF_REQUIRE(memfd_truncate_test(4, 8, F_SEAL_GROW | F_SEAL_SHRINK) == - EPERM); - ATF_REQUIRE(memfd_truncate_test(8, 4, F_SEAL_GROW | F_SEAL_SHRINK) == - EPERM); - ATF_REQUIRE(memfd_truncate_test(4, 4, F_SEAL_GROW | F_SEAL_SHRINK) == - 0); -} - -ATF_TC_WITHOUT_HEAD(get_seals); -ATF_TC_BODY(get_seals, tc) -{ - int fd; - int seals; - - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - ATF_REQUIRE(fcntl(fd, F_GET_SEALS) == 0); - - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW) == 0); - seals = fcntl(fd, F_GET_SEALS); - ATF_REQUIRE(seals == (F_SEAL_WRITE | F_SEAL_GROW)); - - close(fd); -} - -ATF_TC_WITHOUT_HEAD(dup_seals); -ATF_TC_BODY(dup_seals, tc) -{ - char buf[8]; - int fd, fdx; - int seals; - - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - ATF_REQUIRE((fdx = dup(fd)) != -1); - ATF_REQUIRE(fcntl(fd, F_GET_SEALS) == 0); - - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW) == 0); - seals = fcntl(fd, F_GET_SEALS); - ATF_REQUIRE(seals == (F_SEAL_WRITE | F_SEAL_GROW)); - - seals = fcntl(fdx, F_GET_SEALS); - ATF_REQUIRE(seals == (F_SEAL_WRITE | F_SEAL_GROW)); - - /* Make sure the seal's actually being applied at the inode level */ - ATF_REQUIRE(write(fdx, buf, sizeof(buf)) == -1); - ATF_REQUIRE(errno == EPERM); - - ATF_REQUIRE(mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, - fdx, 0) == MAP_FAILED); - ATF_REQUIRE(errno == EACCES); - - close(fd); - close(fdx); -} - -ATF_TC_WITHOUT_HEAD(immutable_seals); -ATF_TC_BODY(immutable_seals, tc) -{ - int fd; - - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_SEAL) == 0); - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_GROW) == -1); - ATF_REQUIRE_MSG(errno == EPERM, - "Added unique grow seal after restricting seals"); - - close(fd); - - /* - * Also check that adding a seal that already exists really doesn't - * do anything once we're sealed. - */ - ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1); - - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SEAL) == 0); - ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_GROW) == -1); - ATF_REQUIRE_MSG(errno == EPERM, - "Added duplicate grow seal after restricting seals"); - close(fd); -} - -ATF_TP_ADD_TCS(tp) -{ - - ATF_TP_ADD_TC(tp, basic); - ATF_TP_ADD_TC(tp, cloexec); - ATF_TP_ADD_TC(tp, disallowed_sealing); - ATF_TP_ADD_TC(tp, write_seal); - ATF_TP_ADD_TC(tp, mmap_write_seal); - ATF_TP_ADD_TC(tp, truncate_seals); - ATF_TP_ADD_TC(tp, get_seals); - ATF_TP_ADD_TC(tp, dup_seals); - ATF_TP_ADD_TC(tp, immutable_seals); - return (atf_no_error()); -} Index: tests/sys/posixshm/Makefile =================================================================== --- tests/sys/posixshm/Makefile +++ tests/sys/posixshm/Makefile @@ -4,6 +4,7 @@ TESTSDIR= ${TESTSBASE}/sys/posixshm +ATF_TESTS_C+= memfd_test ATF_TESTS_C+= posixshm_test .include Index: tools/build/options/WITHOUT_GH_BC =================================================================== --- tools/build/options/WITHOUT_GH_BC +++ tools/build/options/WITHOUT_GH_BC @@ -1,6 +1,6 @@ .\" $FreeBSD$ -Do not install the enhanced -.Xr bc +Set to not build and install the enhanced +.Xr bc 1 and -.Xr dc +.Xr dc 1 programs instead of the traditional FreeBSD versions. Index: tools/build/options/WITH_GH_BC =================================================================== --- tools/build/options/WITH_GH_BC +++ tools/build/options/WITH_GH_BC @@ -1,6 +1,6 @@ .\" $FreeBSD$ -Install the enhanced -.Xr bc +Set this option to install the enhanced +.Xr bc 1 and -.Xr dc +.Xr dc 1 programs instead of the traditional FreeBSD versions. Index: usr.sbin/daemon/daemon.8 =================================================================== --- usr.sbin/daemon/daemon.8 +++ usr.sbin/daemon/daemon.8 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 2, 2019 +.Dd September 22, 2020 .Dt DAEMON 8 .Os .Sh NAME @@ -34,7 +34,7 @@ .Nd run detached from the controlling terminal .Sh SYNOPSIS .Nm -.Op Fl cfrS +.Op Fl cfHrS .Op Fl p Ar child_pidfile .Op Fl P Ar supervisor_pidfile .Op Fl t Ar title @@ -68,6 +68,14 @@ .Pa /dev/null , then stdout and/or stderr is redirected to a file or to syslog as specified by the other options. +.It Fl H +Close +.Pa output_file +and re-open it when signal SIGHUP is received, for interoperability with +.Xr newsyslog 1 +and similar log rotation / archival mechanisms. If +.Fa o +is not specified, this flag is ignored. .It Fl S Enable syslog output. This is implicitly applied if other syslog parameters are provided. @@ -77,6 +85,12 @@ Append output from the daemonized process to .Pa output_file . If the file does not exist, it is created with permissions 0600. +When this option is used together with options +.Fl c and +.Fl H +the absolute path needs to be provided to ensure +.Nm +can re-open the file after a SIGHUP. .It Fl m Ar output_mask Redirect output from the child process stdout (1), stderr (2), or both (3). This value specifies what is sent to syslog and the log file. Index: usr.sbin/daemon/daemon.c =================================================================== --- usr.sbin/daemon/daemon.c +++ usr.sbin/daemon/daemon.c @@ -61,11 +61,15 @@ int logpri; int noclose; int outfd; + const char *outfn; }; static void restrict_process(const char *); static void handle_term(int); static void handle_chld(int); +static void handle_hup(int); +static int open_log(const char *); +static void reopen_log(struct log_params *); static int listen_child(int, struct log_params *); static int get_log_mapping(const char *, const CODE *); static void open_pid_files(const char *, const char *, struct pidfh **, @@ -74,7 +78,8 @@ static void daemon_sleep(time_t, long); static void usage(void); -static volatile sig_atomic_t terminate = 0, child_gone = 0, pid = 0; +static volatile sig_atomic_t terminate = 0, child_gone = 0, pid = 0, + do_log_reopen = 0; int main(int argc, char *argv[]) @@ -84,7 +89,7 @@ sigset_t mask_susp, mask_orig, mask_read, mask_term; struct log_params logpar; int pfd[2] = { -1, -1 }, outfd = -1; - int stdmask, logpri, logfac; + int stdmask, logpri, logfac, log_reopen; struct pidfh *ppfh, *pfh; char *p; @@ -97,9 +102,10 @@ logtag = "daemon"; restart = 0; dosyslog = 0; + log_reopen = 0; outfn = NULL; title = NULL; - while ((ch = getopt(argc, argv, "cfSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) { + while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) { switch (ch) { case 'c': nochdir = 0; @@ -107,6 +113,9 @@ case 'f': noclose = 0; break; + case 'H': + log_reopen = 1; + break; case 'l': logfac = get_log_mapping(optarg, facilitynames); if (logfac == -1) @@ -168,7 +177,7 @@ title = argv[0]; if (outfn) { - outfd = open(outfn, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0600); + outfd = open_log(outfn); if (outfd == -1) err(7, "open"); } @@ -201,7 +210,7 @@ */ pid = -1; if (pidfile || ppidfile || restart || outfd != -1 || dosyslog) { - struct sigaction act_term, act_chld; + struct sigaction act_term, act_chld, act_hup; /* Avoid PID racing with SIGCHLD and SIGTERM. */ memset(&act_term, 0, sizeof(act_term)); @@ -214,6 +223,10 @@ sigemptyset(&act_chld.sa_mask); sigaddset(&act_chld.sa_mask, SIGTERM); + memset(&act_hup, 0, sizeof(act_hup)); + act_hup.sa_handler = handle_hup; + sigemptyset(&act_hup.sa_mask); + /* Block these when avoiding racing before sigsuspend(). */ sigemptyset(&mask_susp); sigaddset(&mask_susp, SIGTERM); @@ -251,6 +264,12 @@ logpar.dosyslog = dosyslog; logpar.logpri = logpri; logpar.noclose = noclose; + logpar.outfn = outfn; + if (log_reopen && outfd >= 0 && + sigaction(SIGHUP, &act_hup, NULL) == -1) { + warn("sigaction"); + goto exit; + } restart: if (pipe(pfd)) err(1, "pipe"); @@ -465,6 +484,8 @@ assert(logpar); assert(bytes_read < LBUF_SIZE - 1); + if (do_log_reopen) + reopen_log(logpar); rv = read(fd, buf + bytes_read, LBUF_SIZE - bytes_read - 1); if (rv > 0) { unsigned char *cp; @@ -543,9 +564,9 @@ } static void -handle_chld(int signo) +handle_chld(int signo __unused) { - (void)signo; + for (;;) { int rv = waitpid(-1, NULL, WNOHANG); if (pid == rv) { @@ -558,11 +579,37 @@ } } +static void +handle_hup(int signo __unused) +{ + + do_log_reopen = 1; +} + +static int +open_log(const char *outfn) +{ + + return open(outfn, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0600); +} + +static void +reopen_log(struct log_params *lpp) +{ + int outfd; + + do_log_reopen = 0; + outfd = open_log(lpp->outfn); + if (lpp->outfd >= 0) + close(lpp->outfd); + lpp->outfd = outfd; +} + static void usage(void) { (void)fprintf(stderr, - "usage: daemon [-cfrS] [-p child_pidfile] [-P supervisor_pidfile]\n" + "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n" " [-u user] [-o output_file] [-t title]\n" " [-l syslog_facility] [-s syslog_priority]\n" " [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"