diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-09-11 18:41:00 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-09-11 18:41:00 +0000 |
| commit | 3af64f03119a159ac15eb75b92d346705b490385 (patch) | |
| tree | ccf01a63517d6acf2fcf883b298f5a384b814df9 /sys | |
| parent | da2d1e9d2582eece6aad948897489ca0b5d64d73 (diff) | |
| parent | de35521a3bbfa50aa7c6dc6852a78099254da094 (diff) | |
Notes
Diffstat (limited to 'sys')
99 files changed, 1723 insertions, 688 deletions
diff --git a/sys/amd64/amd64/efirt_machdep.c b/sys/amd64/amd64/efirt_machdep.c index da7783043a24..80ffa66f5ec4 100644 --- a/sys/amd64/amd64/efirt_machdep.c +++ b/sys/amd64/amd64/efirt_machdep.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include <machine/vmparam.h> #include <vm/vm.h> #include <vm/pmap.h> +#include <vm/vm_extern.h> #include <vm/vm_map.h> #include <vm/vm_object.h> #include <vm/vm_page.h> @@ -266,6 +267,7 @@ efi_arch_enter(void) curpmap = PCPU_GET(curpmap); PMAP_LOCK_ASSERT(curpmap, MA_OWNED); + curthread->td_md.md_efirt_dis_pf = vm_fault_disable_pagefaults(); /* * IPI TLB shootdown handler invltlb_pcid_handler() reloads @@ -300,6 +302,7 @@ efi_arch_leave(void) curpmap->pm_pcids[PCPU_GET(cpuid)].pm_pcid : 0)); if (!pmap_pcid_enabled) invltlb(); + vm_fault_enable_pagefaults(curthread->td_md.md_efirt_dis_pf); } /* XXX debug stuff */ diff --git a/sys/amd64/amd64/efirt_support.S b/sys/amd64/amd64/efirt_support.S new file mode 100644 index 000000000000..cd578eddcfb1 --- /dev/null +++ b/sys/amd64/amd64/efirt_support.S @@ -0,0 +1,116 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Konstantin Belousov <kib@FreeBSD.org> + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * + * $FreeBSD$ + */ + +#include <machine/asmacros.h> + +#include "assym.inc" + + .text +ENTRY(efi_rt_arch_call) + pushq %rbp + movq %rsp, %rbp + + movq %rbx, EC_RBX(%rdi) + movq %rsp, EC_RSP(%rdi) + movq %rbp, EC_RBP(%rdi) + movq %r12, EC_R12(%rdi) + movq %r13, EC_R13(%rdi) + movq %r14, EC_R14(%rdi) + movq %r15, EC_R15(%rdi) + movq PCPU(CURTHREAD), %rax + movq %rdi, TD_MD+MD_EFIRT_TMP(%rax) + movq PCPU(CURPCB), %rsi + + movl EC_ARGCNT(%rdi), %ecx + movl %ecx, %ebx + movl $4, %eax + cmpl %eax, %ecx + cmovbl %eax, %ecx + shll $3, %ecx + subq %rcx, %rsp + + cmpl $0, %ebx + jz 1f + movq EC_ARG1(%rdi), %rcx + decl %ebx + jz 1f + movq EC_ARG2(%rdi), %rdx + decl %ebx + jz 1f + movq EC_ARG3(%rdi), %r8 + decl %ebx + jz 1f + movq EC_ARG4(%rdi), %r9 + decl %ebx + jz 1f + movq EC_ARG5(%rdi), %rax + movq %rax, 4*8(%rsp) + decl %ebx + jz 1f + movq $efi_rt_panic_str, %rdi + call panic +1: movq EC_FPTR(%rdi), %rax + movq $efi_rt_fault, PCB_ONFAULT(%rsi) + callq *%rax + + movq PCPU(CURTHREAD), %rbx + movq TD_MD+MD_EFIRT_TMP(%rbx), %rdi + movq %rax, EC_EFI_STATUS(%rdi) + movq PCPU(CURPCB), %rsi + xorl %eax, %eax + movq %rax, PCB_ONFAULT(%rsi) + +efi_rt_arch_call_tail: + movq EC_R15(%rdi), %r15 + movq EC_R14(%rdi), %r14 + movq EC_R13(%rdi), %r13 + movq EC_R12(%rdi), %r12 + movq EC_RBP(%rdi), %rbp + movq EC_RSP(%rdi), %rsp + movq EC_RBX(%rdi), %rbx + + popq %rbp + ret +END(efi_rt_arch_call) + +ENTRY(efi_rt_fault) + xorl %eax, %eax + movq PCPU(CURPCB), %rsi + movq %rax, PCB_ONFAULT(%rsi) + movl $EFAULT, %eax + movq PCPU(CURTHREAD), %rbx + movq TD_MD+MD_EFIRT_TMP(%rbx), %rdi + jmp efi_rt_arch_call_tail +END(efi_rt_fault) + +efi_rt_panic_str: .asciz "efi_rt_arch_call: too many args" diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index d61b5c7bb6df..4d069388ee93 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include <machine/sigframe.h> #include <machine/proc.h> #include <machine/segments.h> +#include <machine/efi.h> ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace)); ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap)); @@ -77,12 +78,15 @@ ASSYM(P_MD, offsetof(struct proc, p_md)); ASSYM(MD_LDT, offsetof(struct mdproc, md_ldt)); ASSYM(MD_LDT_SD, offsetof(struct mdproc, md_ldt_sd)); +ASSYM(MD_EFIRT_TMP, offsetof(struct mdthread, md_efirt_tmp)); + ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); ASSYM(TD_PFLAGS, offsetof(struct thread, td_pflags)); ASSYM(TD_PROC, offsetof(struct thread, td_proc)); ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); +ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); @@ -249,3 +253,19 @@ ASSYM(__FreeBSD_version, __FreeBSD_version); #ifdef HWPMC_HOOKS ASSYM(PMC_FN_USER_CALLCHAIN, PMC_FN_USER_CALLCHAIN); #endif + +ASSYM(EC_EFI_STATUS, offsetof(struct efirt_callinfo, ec_efi_status)); +ASSYM(EC_FPTR, offsetof(struct efirt_callinfo, ec_fptr)); +ASSYM(EC_ARGCNT, offsetof(struct efirt_callinfo, ec_argcnt)); +ASSYM(EC_ARG1, offsetof(struct efirt_callinfo, ec_arg1)); +ASSYM(EC_ARG2, offsetof(struct efirt_callinfo, ec_arg2)); +ASSYM(EC_ARG3, offsetof(struct efirt_callinfo, ec_arg3)); +ASSYM(EC_ARG4, offsetof(struct efirt_callinfo, ec_arg4)); +ASSYM(EC_ARG5, offsetof(struct efirt_callinfo, ec_arg5)); +ASSYM(EC_RBX, offsetof(struct efirt_callinfo, ec_rbx)); +ASSYM(EC_RSP, offsetof(struct efirt_callinfo, ec_rsp)); +ASSYM(EC_RBP, offsetof(struct efirt_callinfo, ec_rbp)); +ASSYM(EC_R12, offsetof(struct efirt_callinfo, ec_r12)); +ASSYM(EC_R13, offsetof(struct efirt_callinfo, ec_r13)); +ASSYM(EC_R14, offsetof(struct efirt_callinfo, ec_r14)); +ASSYM(EC_R15, offsetof(struct efirt_callinfo, ec_r15)); diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index cbd76aa48585..8cb09df626be 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -7582,9 +7582,13 @@ pmap_activate_boot(pmap_t pmap) CPU_SET(cpuid, &pmap->pm_active); #endif PCPU_SET(curpmap, pmap); - kcr3 = pmap->pm_cr3; - if (pmap_pcid_enabled) - kcr3 |= pmap->pm_pcids[cpuid].pm_pcid | CR3_PCID_SAVE; + if (pti) { + kcr3 = pmap->pm_cr3; + if (pmap_pcid_enabled) + kcr3 |= pmap->pm_pcids[cpuid].pm_pcid | CR3_PCID_SAVE; + } else { + kcr3 = PMAP_NO_CR3; + } PCPU_SET(kcr3, kcr3); PCPU_SET(ucr3, PMAP_NO_CR3); } diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index e010c4eef64c..714f100a9749 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -312,9 +312,10 @@ ENTRY(copyout_smap) movsq movb %dl,%cl andb $7,%cl + je 1f rep movsb - clac +1: clac done_copyout: xorl %eax,%eax @@ -361,6 +362,7 @@ ENTRY(copyin_nosmap) movsq movb %al,%cl andb $7,%cl /* copy remaining bytes */ + je done_copyin rep movsb @@ -393,10 +395,10 @@ ENTRY(copyin_smap) movsq movb %al,%cl andb $7,%cl /* copy remaining bytes */ - je done_copyin + je 1f rep movsb - clac +1: clac done_copyin: xorl %eax,%eax @@ -912,6 +914,8 @@ ENTRY(copyinstr_smap) subq %rsi,%rax jbe cpystrflt + stac + /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ cmpq %rdx,%rax jae 1f @@ -922,31 +926,19 @@ ENTRY(copyinstr_smap) 2: decq %rdx - jz copyinstr_toolong + jz copyinstr_toolong_smap - stac lodsb stosb - clac orb %al,%al jnz 2b + clac + copyinstr_succ: /* Success -- 0 byte reached */ decq %rdx xorl %eax,%eax - jmp cpystrflt_x -copyinstr_toolong: - /* rdx is zero - return ENAMETOOLONG or EFAULT */ - movq $VM_MAXUSER_ADDRESS,%rax - cmpq %rax,%rsi - jae cpystrflt - movq $ENAMETOOLONG,%rax - jmp cpystrflt_x - - /* Fault entry clears PSL.AC */ -cpystrflt: - movq $EFAULT,%rax cpystrflt_x: /* set *lencopied and return %eax */ @@ -960,6 +952,21 @@ cpystrflt_x: 1: POP_FRAME_POINTER ret + /* Fault entry clears PSL.AC */ +cpystrflt: + movq $EFAULT,%rax + jmp cpystrflt_x + +copyinstr_toolong_smap: + clac +copyinstr_toolong: + /* rdx is zero - return ENAMETOOLONG or EFAULT */ + movq $VM_MAXUSER_ADDRESS,%rax + cmpq %rax,%rsi + jae cpystrflt + movq $ENAMETOOLONG,%rax + jmp cpystrflt_x + END(copyinstr_smap) /* diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 019decb837ac..4d03da234f19 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -806,7 +806,7 @@ trap_pfault(struct trapframe *frame, int usermode) * If nx protection of the usermode portion of kernel page * tables caused trap, panic. */ - if (PCPU_GET(curpmap)->pm_ucr3 != PMAP_NO_CR3 && usermode && + if (usermode && PCPU_GET(curpmap)->pm_ucr3 != PMAP_NO_CR3 && pg_nx != 0 && (frame->tf_err & (PGEX_P | PGEX_W | PGEX_U | PGEX_I)) == (PGEX_P | PGEX_U | PGEX_I) && (curpcb->pcb_saved_ucr3 & ~CR3_PCID_MASK)== diff --git a/sys/amd64/include/efi.h b/sys/amd64/include/efi.h index eaea8d03276c..082223792ac0 100644 --- a/sys/amd64/include/efi.h +++ b/sys/amd64/include/efi.h @@ -48,9 +48,30 @@ #ifdef _KERNEL #include <isa/rtc.h> -#define EFI_TIME_LOCK() mtx_lock(&atrtc_time_lock); -#define EFI_TIME_UNLOCK() mtx_unlock(&atrtc_time_lock); -#define EFI_TIME_OWNED() mtx_assert(&atrtc_time_lock, MA_OWNED); +#define EFI_TIME_LOCK() mtx_lock(&atrtc_time_lock) +#define EFI_TIME_UNLOCK() mtx_unlock(&atrtc_time_lock) +#define EFI_TIME_OWNED() mtx_assert(&atrtc_time_lock, MA_OWNED) + +#define EFI_RT_HANDLE_FAULTS_DEFAULT 1 #endif +struct efirt_callinfo { + const char *ec_name; + register_t ec_efi_status; + register_t ec_fptr; + register_t ec_argcnt; + register_t ec_arg1; + register_t ec_arg2; + register_t ec_arg3; + register_t ec_arg4; + register_t ec_arg5; + register_t ec_rbx; + register_t ec_rsp; + register_t ec_rbp; + register_t ec_r12; + register_t ec_r13; + register_t ec_r14; + register_t ec_r15; +}; + #endif /* __AMD64_INCLUDE_EFI_H_ */ diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h index f52c71208e64..54f5b416a7d4 100644 --- a/sys/amd64/include/proc.h +++ b/sys/amd64/include/proc.h @@ -62,6 +62,8 @@ struct mdthread { register_t md_saved_flags; /* (k) */ register_t md_spurflt_addr; /* (k) Spurious page fault address. */ struct pmap_invl_gen md_invl_gen; + register_t md_efirt_tmp; /* (k) */ + int md_efirt_dis_pf; /* (k) */ }; struct mdproc { diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index 0b6d90be053e..9ff0ec110b54 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -497,8 +497,7 @@ arm_gic_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) switch(which) { case GIC_IVAR_HW_REV: - KASSERT(GICD_IIDR_VAR(sc->gic_iidr) < 3 && - GICD_IIDR_VAR(sc->gic_iidr) != 0, + KASSERT(GICD_IIDR_VAR(sc->gic_iidr) < 3, ("arm_gic_read_ivar: Unknown IIDR revision %u (%.08x)", GICD_IIDR_VAR(sc->gic_iidr), sc->gic_iidr)); *result = GICD_IIDR_VAR(sc->gic_iidr); diff --git a/sys/arm/arm/gic_acpi.c b/sys/arm/arm/gic_acpi.c index 2ca65fcaf80c..40928b2b2b19 100644 --- a/sys/arm/arm/gic_acpi.c +++ b/sys/arm/arm/gic_acpi.c @@ -34,6 +34,7 @@ * SUCH DAMAGE. */ +#include "opt_acpi.h" #include "opt_platform.h" #include <sys/cdefs.h> @@ -217,7 +218,7 @@ gic_acpi_attach(device_t dev) if (err != 0) return (err); - xref = 0; + xref = ACPI_INTR_XREF; /* * Now, when everything is initialized, it's right time to diff --git a/sys/arm/arm/physmem.c b/sys/arm/arm/physmem.c index 66c74c9cd731..8a97f9883451 100644 --- a/sys/arm/arm/physmem.c +++ b/sys/arm/arm/physmem.c @@ -48,8 +48,8 @@ __FBSDID("$FreeBSD$"); * that can be allocated, or both, depending on the exclusion flags associated * with the region. */ -#define MAX_HWCNT 10 -#define MAX_EXCNT 10 +#define MAX_HWCNT 16 +#define MAX_EXCNT 16 #if defined(__arm__) #define MAX_PHYS_ADDR 0xFFFFFFFFull @@ -359,7 +359,8 @@ arm_physmem_hardware_region(uint64_t pa, uint64_t sz) /* * Add an exclusion region. */ -void arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t exflags) +void +arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t exflags) { vm_offset_t adj; @@ -371,8 +372,10 @@ void arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t exflags) pa = trunc_page(pa); sz = round_page(sz + adj); - if (excnt < nitems(exregions)) - excnt = insert_region(exregions, excnt, pa, sz, exflags); + if (excnt >= nitems(exregions)) + panic("failed to exclude region %#jx-%#jx", (uintmax_t)pa, + (uintmax_t)(pa + sz)); + excnt = insert_region(exregions, excnt, pa, sz, exflags); } size_t diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c index ecf698a0208e..1ed3a0f6c4d2 100644 --- a/sys/arm/ti/omap4/omap4_prcm_clks.c +++ b/sys/arm/ti/omap4/omap4_prcm_clks.c @@ -176,6 +176,7 @@ struct omap4_prcm_softc { struct resource *sc_res; int sc_rid; int sc_instance; + int attach_done; }; static int omap4_clk_generic_activate(struct ti_clock_dev *clkdev); @@ -1446,10 +1447,8 @@ static int omap4_prcm_attach(device_t dev) { struct omap4_prcm_softc *sc; - unsigned int freq; const struct ofw_compat_data *ocd; - sc = device_get_softc(dev); ocd = ofw_bus_search_compatible(dev, compat_data); sc->sc_instance = (int)ocd->ocd_data; @@ -1463,6 +1462,22 @@ omap4_prcm_attach(device_t dev) ti_cpu_reset = omap4_prcm_reset; + return (0); +} + +static void +omap4_prcm_new_pass(device_t dev) +{ + struct omap4_prcm_softc *sc = device_get_softc(dev); + unsigned int freq; + + if (sc->attach_done || + bus_current_pass < (BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY)) { + bus_generic_new_pass(dev); + return; + } + sc->attach_done = 1; + /* * In order to determine ARM frequency we need both RPM and CM1 * instances up and running. So wait until all CRM devices are @@ -1473,12 +1488,16 @@ omap4_prcm_attach(device_t dev) arm_tmr_change_frequency(freq / 2); } - return (0); + return; } static device_method_t omap4_prcm_methods[] = { DEVMETHOD(device_probe, omap4_prcm_probe), DEVMETHOD(device_attach, omap4_prcm_attach), + + /* Bus interface */ + DEVMETHOD(bus_new_pass, omap4_prcm_new_pass), + {0, 0}, }; @@ -1491,5 +1510,5 @@ static driver_t omap4_prcm_driver = { static devclass_t omap4_prcm_devclass; EARLY_DRIVER_MODULE(omap4_prcm, simplebus, omap4_prcm_driver, - omap4_prcm_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY); + omap4_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(omap4_prcm, 1); diff --git a/sys/arm64/arm64/efirt_machdep.c b/sys/arm64/arm64/efirt_machdep.c index 44e3a04ac372..cf092ff0dab7 100644 --- a/sys/arm64/arm64/efirt_machdep.c +++ b/sys/arm64/arm64/efirt_machdep.c @@ -268,3 +268,10 @@ efi_arch_leave(void) "isb \n" : : "r"(td->td_proc->p_md.md_l0addr)); } + +int +efi_rt_arch_call(struct efirt_callinfo *ec) +{ + + panic("not implemented"); +} diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index f1ba40cfa9ae..dc243c958a63 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -982,6 +982,7 @@ cache_setup(void) void initarm(struct arm64_bootparams *abp) { + struct efi_fb *efifb; struct efi_map_header *efihdr; struct pcpu *pcpup; char *env; @@ -1031,6 +1032,13 @@ initarm(struct arm64_bootparams *abp) EXFLAG_NODUMP | EXFLAG_NOALLOC); #endif + /* Exclude the EFI framebuffer from our view of physical memory. */ + efifb = (struct efi_fb *)preload_search_info(kmdp, + MODINFO_METADATA | MODINFOMD_EFI_FB); + if (efifb != NULL) + arm_physmem_exclude_region(efifb->fb_addr, efifb->fb_size, + EXFLAG_NOALLOC); + /* Set the pcpu data, this is needed by pmap_bootstrap */ pcpup = &__pcpu[0]; pcpu_init(pcpup, 0, sizeof(struct pcpu)); diff --git a/sys/arm64/include/efi.h b/sys/arm64/include/efi.h index 6673adccb34f..a8fddfad8d0f 100644 --- a/sys/arm64/include/efi.h +++ b/sys/arm64/include/efi.h @@ -39,6 +39,20 @@ #define EFI_TIME_LOCK() #define EFI_TIME_UNLOCK() #define EFI_TIME_OWNED() + +#define EFI_RT_HANDLE_FAULTS_DEFAULT 0 #endif +struct efirt_callinfo { + const char *ec_name; + register_t ec_efi_status; + register_t ec_fptr; + register_t ec_argcnt; + register_t ec_arg1; + register_t ec_arg2; + register_t ec_arg3; + register_t ec_arg4; + register_t ec_arg5; +}; + #endif /* __ARM64_INCLUDE_EFI_H_ */ diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 94bc97bc033d..2606327d3851 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -2943,8 +2943,17 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } if (lun_req->args != NULL) { - lun_req->args_nvl = nvlist_unpack(lun_req->args, + packed = malloc(lun_req->args_len, M_CTL, M_WAITOK); + if (copyin(lun_req->args, packed, lun_req->args_len) != 0) { + free(packed, M_CTL); + lun_req->status = CTL_LUN_ERROR; + snprintf(lun_req->error_str, sizeof(lun_req->error_str), + "Cannot copyin args."); + break; + } + lun_req->args_nvl = nvlist_unpack(packed, lun_req->args_len, 0); + free(packed, M_CTL); if (lun_req->args_nvl == NULL) { lun_req->status = CTL_LUN_ERROR; @@ -3211,8 +3220,17 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } if (req->args != NULL) { - req->args_nvl = nvlist_unpack(req->args, + packed = malloc(req->args_len, M_CTL, M_WAITOK); + if (copyin(req->args, packed, req->args_len) != 0) { + free(packed, M_CTL); + req->status = CTL_LUN_ERROR; + snprintf(req->error_str, sizeof(req->error_str), + "Cannot copyin args."); + break; + } + req->args_nvl = nvlist_unpack(packed, req->args_len, 0); + free(packed, M_CTL); if (req->args_nvl == NULL) { req->status = CTL_LUN_ERROR; diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index 2d3766a8e73b..d5be20c2a215 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -1434,7 +1434,7 @@ cfiscsi_offline(void *arg) struct cfiscsi_softc *softc; struct cfiscsi_target *ct; struct cfiscsi_session *cs; - int online; + int error, online; ct = (struct cfiscsi_target *)arg; softc = ct->ct_softc; @@ -1447,17 +1447,23 @@ cfiscsi_offline(void *arg) ct->ct_online = 0; online = --softc->online; - TAILQ_FOREACH(cs, &softc->sessions, cs_next) { - if (cs->cs_target == ct) - cfiscsi_session_terminate(cs); - } do { TAILQ_FOREACH(cs, &softc->sessions, cs_next) { if (cs->cs_target == ct) + cfiscsi_session_terminate(cs); + } + TAILQ_FOREACH(cs, &softc->sessions, cs_next) { + if (cs->cs_target == ct) break; } - if (cs != NULL) - cv_wait(&softc->sessions_cv, &softc->lock); + if (cs != NULL) { + error = cv_wait_sig(&softc->sessions_cv, &softc->lock); + if (error != 0) { + CFISCSI_SESSION_DEBUG(cs, + "cv_wait failed with error %d\n", error); + break; + } + } } while (cs != NULL && ct->ct_online == 0); mtx_unlock(&softc->lock); if (online > 0) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index b825a4c92e9c..2bc065e12509 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -661,6 +661,12 @@ typedef struct arc_stats { * Number of bytes consumed by bonus buffers. */ kstat_named_t arcstat_bonus_size; +#if defined(__FreeBSD__) && defined(COMPAT_FREEBSD11) + /* + * Sum of the previous three counters, provided for compatibility. + */ + kstat_named_t arcstat_other_size; +#endif /* * Total number of bytes consumed by ARC buffers residing in the * arc_anon state. This includes *all* buffers in the arc_anon @@ -875,6 +881,9 @@ static arc_stats_t arc_stats = { { "dbuf_size", KSTAT_DATA_UINT64 }, { "dnode_size", KSTAT_DATA_UINT64 }, { "bonus_size", KSTAT_DATA_UINT64 }, +#if defined(__FreeBSD__) && defined(COMPAT_FREEBSD11) + { "other_size", KSTAT_DATA_UINT64 }, +#endif { "anon_size", KSTAT_DATA_UINT64 }, { "anon_evictable_data", KSTAT_DATA_UINT64 }, { "anon_evictable_metadata", KSTAT_DATA_UINT64 }, @@ -4438,6 +4447,12 @@ arc_adjust(void) } /* + * Re-sum ARC stats after the first round of evictions. + */ + asize = aggsum_value(&arc_size); + ameta = aggsum_value(&arc_meta_used); + + /* * Adjust MFU size * * Now that we've tried to evict enough from the MRU to get its @@ -6825,6 +6840,11 @@ arc_kstat_update(kstat_t *ksp, int rw) ARCSTAT(arcstat_bonus_size) = aggsum_value(&astat_bonus_size); ARCSTAT(arcstat_dnode_size) = aggsum_value(&astat_dnode_size); ARCSTAT(arcstat_dbuf_size) = aggsum_value(&astat_dbuf_size); +#if defined(__FreeBSD__) && defined(COMPAT_FREEBSD11) + ARCSTAT(arcstat_other_size) = aggsum_value(&astat_bonus_size) + + aggsum_value(&astat_dnode_size) + + aggsum_value(&astat_dbuf_size); +#endif ARCSTAT(arcstat_l2_hdr_size) = aggsum_value(&astat_l2_hdr_size); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index ef252a32caeb..efbf36e86339 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -2496,12 +2496,11 @@ extern void dtrace_helpers_destroy(proc_t *); #elif defined(__riscv) -#define SD_RA_SP_MASK 0x01fff07f -#define SD_RA_SP 0x00113023 - #define DTRACE_INVOP_SD 1 -#define DTRACE_INVOP_RET 2 -#define DTRACE_INVOP_NOP 3 +#define DTRACE_INVOP_C_SDSP 2 +#define DTRACE_INVOP_RET 3 +#define DTRACE_INVOP_C_RET 4 +#define DTRACE_INVOP_NOP 5 #endif diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c index 3957a1b93665..68d98db30c83 100644 --- a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c @@ -19,7 +19,7 @@ * * CDDL HEADER END * - * Portions Copyright 2016 Ruslan Bukin <br@bsdpad.com> + * Portions Copyright 2016-2018 Ruslan Bukin <br@bsdpad.com> * * $FreeBSD$ * @@ -42,8 +42,8 @@ __FBSDID("$FreeBSD$"); #include <sys/dtrace_impl.h> #include <sys/dtrace_bsd.h> #include <machine/vmparam.h> +#include <machine/encoding.h> #include <machine/riscvreg.h> -#include <machine/riscv_opcode.h> #include <machine/clock.h> #include <machine/frame.h> #include <machine/trap.h> @@ -77,7 +77,6 @@ dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax) return (0); } - void dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t)) { @@ -238,29 +237,58 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, } static int +match_opcode(uint32_t insn, int match, int mask) +{ + + if (((insn ^ match) & mask) == 0) + return (1); + + return (0); +} + +static int dtrace_invop_start(struct trapframe *frame) { - int data, invop, reg, update_sp; - register_t arg1, arg2; register_t *sp; + uint32_t uimm; uint32_t imm; - InstFmt i; - int offs; - int tmp; + int invop; invop = dtrace_invop(frame->tf_sepc, frame, frame->tf_sepc); - if (invop == RISCV_INSN_RET) { + if (match_opcode(invop, (MATCH_SD | RS2_RA | RS1_SP), + (MASK_SD | RS2_MASK | RS1_MASK))) { + /* Non-compressed store of ra to sp */ + imm = (invop >> 7) & 0x1f; + imm |= ((invop >> 25) & 0x7f) << 5; + sp = (register_t *)((uint8_t *)frame->tf_sp + imm); + *sp = frame->tf_ra; + frame->tf_sepc += INSN_SIZE; + return (0); + } + + if (match_opcode(invop, (MATCH_JALR | (X_RA << RS1_SHIFT)), + (MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK))) { + /* Non-compressed ret */ frame->tf_sepc = frame->tf_ra; return (0); } - if ((invop & SD_RA_SP_MASK) == SD_RA_SP) { - i.word = invop; - imm = i.SType.imm0_4 | (i.SType.imm5_11 << 5); - sp = (register_t *)((uint8_t *)frame->tf_sp + imm); + if (match_opcode(invop, (MATCH_C_SDSP | RS2_C_RA), + (MASK_C_SDSP | RS2_C_MASK))) { + /* 'C'-compressed store of ra to sp */ + uimm = ((invop >> 10) & 0x7) << 3; + uimm |= ((invop >> 7) & 0x7) << 6; + sp = (register_t *)((uint8_t *)frame->tf_sp + uimm); *sp = frame->tf_ra; - frame->tf_sepc += INSN_SIZE; + frame->tf_sepc += INSN_C_SIZE; + return (0); + } + + if (match_opcode(invop, (MATCH_C_JR | (X_RA << RD_SHIFT)), + (MASK_C_JR | RD_MASK))) { + /* 'C'-compressed ret */ + frame->tf_sepc = frame->tf_ra; return (0); } diff --git a/sys/cddl/dev/fbt/fbt.c b/sys/cddl/dev/fbt/fbt.c index 590967ade7b3..775100c0a68b 100644 --- a/sys/cddl/dev/fbt/fbt.c +++ b/sys/cddl/dev/fbt/fbt.c @@ -212,7 +212,7 @@ fbt_destroy_one(fbt_probe_t *fbt) ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint); for (hash = fbt_probetab[ndx], hashprev = NULL; hash != NULL; - hash = hash->fbtp_hashnext, hashprev = hash) { + hashprev = hash, hash = hash->fbtp_hashnext) { if (hash == fbt) { if ((next = fbt->fbtp_tracenext) != NULL) next->fbtp_hashnext = hash->fbtp_hashnext; diff --git a/sys/cddl/dev/fbt/riscv/fbt_isa.c b/sys/cddl/dev/fbt/riscv/fbt_isa.c index 519784bbfcdf..4c29cee46b53 100644 --- a/sys/cddl/dev/fbt/riscv/fbt_isa.c +++ b/sys/cddl/dev/fbt/riscv/fbt_isa.c @@ -21,7 +21,7 @@ * Portions Copyright 2006-2008 John Birrell jb@freebsd.org * Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org * Portions Copyright 2013 Howard Su howardsu@freebsd.org - * Portions Copyright 2016 Ruslan Bukin <br@bsdpad.com> + * Portions Copyright 2016-2018 Ruslan Bukin <br@bsdpad.com> * * $FreeBSD$ */ @@ -37,10 +37,12 @@ #include <sys/dtrace.h> #include <machine/riscvreg.h> +#include <machine/encoding.h> #include "fbt.h" -#define FBT_PATCHVAL (RISCV_INSN_BREAK) +#define FBT_C_PATCHVAL MATCH_C_EBREAK +#define FBT_PATCHVAL MATCH_EBREAK #define FBT_ENTRY "entry" #define FBT_RETURN "return" @@ -73,8 +75,62 @@ void fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val) { - *fbt->fbtp_patchpoint = val; - cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4); + switch(fbt->fbtp_patchval) { + case FBT_C_PATCHVAL: + *(uint16_t *)fbt->fbtp_patchpoint = (uint16_t)val; + cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 2); + break; + case FBT_PATCHVAL: + *fbt->fbtp_patchpoint = val; + cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4); + break; + }; +} + +static int +match_opcode(uint32_t insn, int match, int mask) +{ + + if (((insn ^ match) & mask) == 0) + return (1); + + return (0); +} + +static int +check_c_ret(uint32_t **instr) +{ + uint16_t *instr1; + int i; + + for (i = 0; i < 2; i++) { + instr1 = (uint16_t *)(*instr) + i; + if (match_opcode(*instr1, (MATCH_C_JR | (X_RA << RD_SHIFT)), + (MASK_C_JR | RD_MASK))) { + *instr = (uint32_t *)instr1; + return (1); + } + } + + return (0); +} + +static int +check_c_sdsp(uint32_t **instr) +{ + uint16_t *instr1; + int i; + + for (i = 0; i < 2; i++) { + instr1 = (uint16_t *)(*instr) + i; + if (match_opcode(*instr1, (MATCH_C_SDSP | RS2_C_RA), + (MASK_C_SDSP | RS2_C_MASK))) { + *instr = (uint32_t *)instr1; + return (1); + } + } + + return (0); } int @@ -85,6 +141,8 @@ fbt_provide_module_function(linker_file_t lf, int symindx, uint32_t *instr, *limit; const char *name; char *modname; + int patchval; + int rval; modname = opaque; name = symval->name; @@ -98,8 +156,20 @@ fbt_provide_module_function(linker_file_t lf, int symindx, /* Look for sd operation */ for (; instr < limit; instr++) { - if ((*instr & SD_RA_SP_MASK) == SD_RA_SP) + /* Look for a non-compressed store of ra to sp */ + if (match_opcode(*instr, (MATCH_SD | RS2_RA | RS1_SP), + (MASK_SD | RS2_MASK | RS1_MASK))) { + rval = DTRACE_INVOP_SD; + patchval = FBT_PATCHVAL; break; + } + + /* Look for a 'C'-compressed store of ra to sp. */ + if (check_c_sdsp(&instr)) { + rval = DTRACE_INVOP_C_SDSP; + patchval = FBT_C_PATCHVAL; + break; + } } if (instr >= limit) @@ -113,8 +183,8 @@ fbt_provide_module_function(linker_file_t lf, int symindx, fbt->fbtp_ctl = lf; fbt->fbtp_loadcnt = lf->loadcnt; fbt->fbtp_savedval = *instr; - fbt->fbtp_patchval = FBT_PATCHVAL; - fbt->fbtp_rval = DTRACE_INVOP_SD; + fbt->fbtp_patchval = patchval; + fbt->fbtp_rval = rval; fbt->fbtp_symindx = symindx; fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; @@ -125,8 +195,20 @@ fbt_provide_module_function(linker_file_t lf, int symindx, retfbt = NULL; again: for (; instr < limit; instr++) { - if (*instr == RISCV_INSN_RET) + /* Look for non-compressed return */ + if (match_opcode(*instr, (MATCH_JALR | (X_RA << RS1_SHIFT)), + (MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK))) { + rval = DTRACE_INVOP_RET; + patchval = FBT_PATCHVAL; break; + } + + /* Look for 'C'-compressed return */ + if (check_c_ret(&instr)) { + rval = DTRACE_INVOP_C_RET; + patchval = FBT_C_PATCHVAL; + break; + } } if (instr >= limit) @@ -150,9 +232,9 @@ again: fbt->fbtp_ctl = lf; fbt->fbtp_loadcnt = lf->loadcnt; fbt->fbtp_symindx = symindx; - fbt->fbtp_rval = DTRACE_INVOP_RET; + fbt->fbtp_rval = rval; fbt->fbtp_savedval = *instr; - fbt->fbtp_patchval = FBT_PATCHVAL; + fbt->fbtp_patchval = patchval; fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 93bf50f9502f..0407dd30c7f1 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -134,6 +134,7 @@ amd64/amd64/db_disasm.c optional ddb amd64/amd64/db_interface.c optional ddb amd64/amd64/db_trace.c optional ddb amd64/amd64/efirt_machdep.c optional efirt +amd64/amd64/efirt_support.S optional efirt amd64/amd64/elf_machdep.c standard amd64/amd64/exception.S standard amd64/amd64/fpu.c standard diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk index bc4204dcd0d6..3cd293b3342f 100644 --- a/sys/conf/kern.mk +++ b/sys/conf/kern.mk @@ -132,7 +132,7 @@ INLINE_LIMIT?= 8000 .endif .if ${MACHINE_CPUARCH} == "riscv" -CFLAGS.gcc+= -mcmodel=medany -march=rv64imafd -mabi=lp64 +CFLAGS.gcc+= -mcmodel=medany -march=rv64imafdc -mabi=lp64 INLINE_LIMIT?= 8000 .endif diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 89d40f3ece64..9e83b6379f51 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -46,7 +46,7 @@ TYPE="FreeBSD" REVISION="12.0" -BRANCH="ALPHA3" +BRANCH="ALPHA5" if [ -n "${BRANCH_OVERRIDE}" ]; then BRANCH=${BRANCH_OVERRIDE} fi diff --git a/sys/contrib/rdma/krping/krping.c b/sys/contrib/rdma/krping/krping.c index e97588382710..7b1038c27db7 100644 --- a/sys/contrib/rdma/krping/krping.c +++ b/sys/contrib/rdma/krping/krping.c @@ -2156,7 +2156,7 @@ int krping_doit(char *cmd) goto out; } - cb->cm_id = rdma_create_id(&init_net, krping_cma_event_handler, cb, RDMA_PS_TCP, IB_QPT_RC); + cb->cm_id = rdma_create_id(TD_TO_VNET(curthread), krping_cma_event_handler, cb, RDMA_PS_TCP, IB_QPT_RC); if (IS_ERR(cb->cm_id)) { ret = PTR_ERR(cb->cm_id); printk(KERN_ERR PFX "rdma_create_id error %d\n", ret); diff --git a/sys/crypto/ccp/ccp.c b/sys/crypto/ccp/ccp.c index f6235bc1610b..163fa748b2ef 100644 --- a/sys/crypto/ccp/ccp.c +++ b/sys/crypto/ccp/ccp.c @@ -734,8 +734,10 @@ DRIVER_MODULE(ccp, pci, ccp_driver, ccp_devclass, NULL, NULL); MODULE_VERSION(ccp, 1); MODULE_DEPEND(ccp, crypto, 1, 1, 1); MODULE_DEPEND(ccp, random_device, 1, 1, 1); +#if 0 /* There are enough known issues that we shouldn't load automatically */ MODULE_PNP_INFO("W32:vendor/device", pci, ccp, ccp_ids, sizeof(ccp_ids[0]), nitems(ccp_ids)); +#endif static int ccp_queue_reserve_space(struct ccp_queue *qp, unsigned n, int mflags) diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c index d48074d72d6c..5c1f7fd75d36 100644 --- a/sys/dev/efidev/efirt.c +++ b/sys/dev/efidev/efirt.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2004 Marcel Moolenaar * Copyright (c) 2001 Doug Rabson - * Copyright (c) 2016 The FreeBSD Foundation + * Copyright (c) 2016, 2018 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Konstantin Belousov @@ -293,22 +293,89 @@ efi_get_table(struct uuid *uuid, void **ptr) return (ENOENT); } +static int efi_rt_handle_faults = EFI_RT_HANDLE_FAULTS_DEFAULT; +SYSCTL_INT(_machdep, OID_AUTO, efi_rt_handle_faults, CTLFLAG_RWTUN, + &efi_rt_handle_faults, 0, + "Call EFI RT methods with fault handler wrapper around"); + static int -efi_get_time_locked(struct efi_tm *tm, struct efi_tmcap *tmcap) +efi_rt_arch_call_nofault(struct efirt_callinfo *ec) +{ + + switch (ec->ec_argcnt) { + case 0: + ec->ec_efi_status = ((register_t (*)(void))ec->ec_fptr)(); + break; + case 1: + ec->ec_efi_status = ((register_t (*)(register_t))ec->ec_fptr) + (ec->ec_arg1); + break; + case 2: + ec->ec_efi_status = ((register_t (*)(register_t, register_t)) + ec->ec_fptr)(ec->ec_arg1, ec->ec_arg2); + break; + case 3: + ec->ec_efi_status = ((register_t (*)(register_t, register_t, + register_t))ec->ec_fptr)(ec->ec_arg1, ec->ec_arg2, + ec->ec_arg3); + break; + case 4: + ec->ec_efi_status = ((register_t (*)(register_t, register_t, + register_t, register_t))ec->ec_fptr)(ec->ec_arg1, + ec->ec_arg2, ec->ec_arg3, ec->ec_arg4); + break; + case 5: + ec->ec_efi_status = ((register_t (*)(register_t, register_t, + register_t, register_t, register_t))ec->ec_fptr)( + ec->ec_arg1, ec->ec_arg2, ec->ec_arg3, ec->ec_arg4, + ec->ec_arg5); + break; + default: + panic("efi_rt_arch_call: %d args", (int)ec->ec_argcnt); + } + + return (0); +} + +static int +efi_call(struct efirt_callinfo *ecp) { - efi_status status; int error; - EFI_TIME_OWNED() error = efi_enter(); if (error != 0) return (error); - status = efi_runtime->rt_gettime(tm, tmcap); + error = efi_rt_handle_faults ? efi_rt_arch_call(ecp) : + efi_rt_arch_call_nofault(ecp); efi_leave(); - error = efi_status_to_errno(status); + if (error == 0) + error = efi_status_to_errno(ecp->ec_efi_status); + else if (bootverbose) + printf("EFI %s call faulted, error %d\n", ecp->ec_name, error); return (error); } +#define EFI_RT_METHOD_PA(method) \ + ((uintptr_t)((struct efi_rt *)efi_phys_to_kva((uintptr_t) \ + efi_runtime))->method) + +static int +efi_get_time_locked(struct efi_tm *tm, struct efi_tmcap *tmcap) +{ + struct efirt_callinfo ec; + + EFI_TIME_OWNED(); + if (efi_runtime == NULL) + return (ENXIO); + bzero(&ec, sizeof(ec)); + ec.ec_name = "rt_gettime"; + ec.ec_argcnt = 2; + ec.ec_arg1 = (uintptr_t)tm; + ec.ec_arg2 = (uintptr_t)tmcap; + ec.ec_fptr = EFI_RT_METHOD_PA(rt_gettime); + return (efi_call(&ec)); +} + int efi_get_time(struct efi_tm *tm) { @@ -317,7 +384,7 @@ efi_get_time(struct efi_tm *tm) if (efi_runtime == NULL) return (ENXIO); - EFI_TIME_LOCK() + EFI_TIME_LOCK(); /* * UEFI spec states that the Capabilities argument to GetTime is * optional, but some UEFI implementations choke when passed a NULL @@ -325,7 +392,7 @@ efi_get_time(struct efi_tm *tm) * to workaround such implementations. */ error = efi_get_time_locked(tm, &dummy); - EFI_TIME_UNLOCK() + EFI_TIME_UNLOCK(); return (error); } @@ -337,39 +404,44 @@ efi_get_time_capabilities(struct efi_tmcap *tmcap) if (efi_runtime == NULL) return (ENXIO); - EFI_TIME_LOCK() + EFI_TIME_LOCK(); error = efi_get_time_locked(&dummy, tmcap); - EFI_TIME_UNLOCK() + EFI_TIME_UNLOCK(); return (error); } int efi_reset_system(void) { - int error; + struct efirt_callinfo ec; - error = efi_enter(); - if (error != 0) - return (error); - efi_runtime->rt_reset(EFI_RESET_WARM, 0, 0, NULL); - efi_leave(); - return (EIO); + if (efi_runtime == NULL) + return (ENXIO); + bzero(&ec, sizeof(ec)); + ec.ec_name = "rt_reset"; + ec.ec_argcnt = 4; + ec.ec_arg1 = (uintptr_t)EFI_RESET_WARM; + ec.ec_arg2 = (uintptr_t)0; + ec.ec_arg3 = (uintptr_t)0; + ec.ec_arg4 = (uintptr_t)NULL; + ec.ec_fptr = EFI_RT_METHOD_PA(rt_reset); + return (efi_call(&ec)); } static int efi_set_time_locked(struct efi_tm *tm) { - efi_status status; - int error; + struct efirt_callinfo ec; EFI_TIME_OWNED(); - error = efi_enter(); - if (error != 0) - return (error); - status = efi_runtime->rt_settime(tm); - efi_leave(); - error = efi_status_to_errno(status); - return (error); + if (efi_runtime == NULL) + return (ENXIO); + bzero(&ec, sizeof(ec)); + ec.ec_name = "rt_settime"; + ec.ec_argcnt = 1; + ec.ec_arg1 = (uintptr_t)tm; + ec.ec_fptr = EFI_RT_METHOD_PA(rt_settime); + return (efi_call(&ec)); } int @@ -379,9 +451,9 @@ efi_set_time(struct efi_tm *tm) if (efi_runtime == NULL) return (ENXIO); - EFI_TIME_LOCK() + EFI_TIME_LOCK(); error = efi_set_time_locked(tm); - EFI_TIME_UNLOCK() + EFI_TIME_UNLOCK(); return (error); } @@ -389,47 +461,57 @@ int efi_var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib, size_t *datasize, void *data) { - efi_status status; - int error; + struct efirt_callinfo ec; - error = efi_enter(); - if (error != 0) - return (error); - status = efi_runtime->rt_getvar(name, vendor, attrib, datasize, data); - efi_leave(); - error = efi_status_to_errno(status); - return (error); + if (efi_runtime == NULL) + return (ENXIO); + bzero(&ec, sizeof(ec)); + ec.ec_argcnt = 5; + ec.ec_name = "rt_getvar"; + ec.ec_arg1 = (uintptr_t)name; + ec.ec_arg2 = (uintptr_t)vendor; + ec.ec_arg3 = (uintptr_t)attrib; + ec.ec_arg4 = (uintptr_t)datasize; + ec.ec_arg5 = (uintptr_t)data; + ec.ec_fptr = EFI_RT_METHOD_PA(rt_getvar); + return (efi_call(&ec)); } int efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor) { - efi_status status; - int error; + struct efirt_callinfo ec; - error = efi_enter(); - if (error != 0) - return (error); - status = efi_runtime->rt_scanvar(namesize, name, vendor); - efi_leave(); - error = efi_status_to_errno(status); - return (error); + if (efi_runtime == NULL) + return (ENXIO); + bzero(&ec, sizeof(ec)); + ec.ec_argcnt = 3; + ec.ec_name = "rt_scanvar"; + ec.ec_arg1 = (uintptr_t)namesize; + ec.ec_arg2 = (uintptr_t)name; + ec.ec_arg3 = (uintptr_t)vendor; + ec.ec_fptr = EFI_RT_METHOD_PA(rt_scanvar); + return (efi_call(&ec)); } int efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib, size_t datasize, void *data) { - efi_status status; - int error; + struct efirt_callinfo ec; - error = efi_enter(); - if (error != 0) - return (error); - status = efi_runtime->rt_setvar(name, vendor, attrib, datasize, data); - efi_leave(); - error = efi_status_to_errno(status); - return (error); + if (efi_runtime == NULL) + return (ENXIO); + bzero(&ec, sizeof(ec)); + ec.ec_argcnt = 5; + ec.ec_name = "rt_setvar"; + ec.ec_arg1 = (uintptr_t)name; + ec.ec_arg2 = (uintptr_t)vendor; + ec.ec_arg3 = (uintptr_t)attrib; + ec.ec_arg4 = (uintptr_t)datasize; + ec.ec_arg5 = (uintptr_t)data; + ec.ec_fptr = EFI_RT_METHOD_PA(rt_setvar); + return (efi_call(&ec)); } static int diff --git a/sys/dev/efidev/efirtc.c b/sys/dev/efidev/efirtc.c index b9e06bcc362e..e5a2ec262bf5 100644 --- a/sys/dev/efidev/efirtc.c +++ b/sys/dev/efidev/efirtc.c @@ -74,7 +74,8 @@ efirtc_probe(device_t dev) */ if ((error = efi_get_time(&tm)) != 0) { if (bootverbose) - device_printf(dev, "cannot read EFI realtime clock\n"); + device_printf(dev, "cannot read EFI realtime clock, " + "error %d\n", error); return (error); } device_set_desc(dev, "EFI Realtime Clock"); diff --git a/sys/dev/extres/regulator/regulator.c b/sys/dev/extres/regulator/regulator.c index ef6e5216d7c5..079612a46957 100644 --- a/sys/dev/extres/regulator/regulator.c +++ b/sys/dev/extres/regulator/regulator.c @@ -172,7 +172,7 @@ regulator_shutdown(void *dummy) REG_TOPO_SLOCK(); TUNABLE_INT_FETCH("hw.regulator.disable_unused", &disable); TAILQ_FOREACH(entry, ®node_list, reglist_link) { - if (entry->std_param.always_on == 0 && disable) { + if (!entry->std_param.always_on && disable) { if (bootverbose) printf("regulator: shutting down %s\n", entry->name); @@ -595,8 +595,9 @@ regnode_disable(struct regnode *regnode) REGNODE_XLOCK(regnode); /* Disable regulator for each node in chain, starting from consumer. */ - if ((regnode->enable_cnt == 1) && - ((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) { + if (regnode->enable_cnt == 1 && + (regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0 && + !regnode->std_param.always_on) { rv = REGNODE_ENABLE(regnode, false, &udelay); if (rv != 0) { REGNODE_UNLOCK(regnode); @@ -1048,10 +1049,10 @@ regulator_parse_ofw_stdparam(device_t pdev, phandle_t node, par->enable_delay = 0; if (OF_hasprop(node, "regulator-boot-on")) - par->boot_on = 1; + par->boot_on = true; if (OF_hasprop(node, "regulator-always-on")) - par->always_on = 1; + par->always_on = true; if (OF_hasprop(node, "enable-active-high")) par->enable_active_high = 1; diff --git a/sys/dev/intel/spi.c b/sys/dev/intel/spi.c index 9b229bb74123..e9b9bfc46fb0 100644 --- a/sys/dev/intel/spi.c +++ b/sys/dev/intel/spi.c @@ -480,7 +480,7 @@ error: sc->sc_mem_rid, sc->sc_mem_res); if (sc->sc_irq_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, + bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, sc->sc_irq_res); return (ENXIO); @@ -503,10 +503,10 @@ intelspi_detach(device_t dev) sc->sc_mem_rid, sc->sc_mem_res); if (sc->sc_irq_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, + bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, sc->sc_irq_res); - return (0); + return (bus_generic_detach(dev)); } static device_method_t intelspi_methods[] = { diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c index e1fb720511fb..a6a3465b60d7 100644 --- a/sys/dev/ixgbe/if_ixv.c +++ b/sys/dev/ixgbe/if_ixv.c @@ -1470,6 +1470,7 @@ ixv_initialize_receive_units(if_ctx_t ctx) static void ixv_setup_vlan_support(if_ctx_t ctx) { + struct ifnet *ifp = iflib_get_ifp(ctx); struct adapter *adapter = iflib_get_softc(ctx); struct ixgbe_hw *hw = &adapter->hw; u32 ctrl, vid, vfta, retry; @@ -1483,19 +1484,28 @@ ixv_setup_vlan_support(if_ctx_t ctx) if (adapter->num_vlans == 0) return; - /* Enable the queues */ - for (int i = 0; i < adapter->num_rx_queues; i++) { - ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); - ctrl |= IXGBE_RXDCTL_VME; - IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl); - /* - * Let Rx path know that it needs to store VLAN tag - * as part of extra mbuf info. - */ - adapter->rx_queues[i].rxr.vtag_strip = TRUE; + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { + /* Enable the queues */ + for (int i = 0; i < adapter->num_rx_queues; i++) { + ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); + ctrl |= IXGBE_RXDCTL_VME; + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl); + /* + * Let Rx path know that it needs to store VLAN tag + * as part of extra mbuf info. + */ + adapter->rx_queues[i].rxr.vtag_strip = TRUE; + } } /* + * If filtering VLAN tags is disabled, + * there is no need to fill VLAN Filter Table Array (VFTA). + */ + if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) + return; + + /* * A soft reset zero's out the VFTA, so * we need to repopulate it now. */ diff --git a/sys/dev/ixgbe/ix_txrx.c b/sys/dev/ixgbe/ix_txrx.c index 3fef6c5889d1..91c92c56a6df 100644 --- a/sys/dev/ixgbe/ix_txrx.c +++ b/sys/dev/ixgbe/ix_txrx.c @@ -430,7 +430,8 @@ ixgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) rxd->wb.upper.status_error = 0; eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0); - if (staterr & IXGBE_RXD_STAT_VP) { + + if ( (rxr->vtag_strip) && (staterr & IXGBE_RXD_STAT_VP) ) { vtag = le16toh(rxd->wb.upper.vlan); } else { vtag = 0; diff --git a/sys/dev/mlx5/driver.h b/sys/dev/mlx5/driver.h index 82c96ae42278..15bcb3cc3ae4 100644 --- a/sys/dev/mlx5/driver.h +++ b/sys/dev/mlx5/driver.h @@ -682,6 +682,9 @@ struct mlx5_core_dev { struct mlx5_flow_root_namespace *sniffer_tx_root_ns; u32 num_q_counter_allocated[MLX5_INTERFACE_NUMBER]; struct mlx5_dump_data *dump_data; + + struct sysctl_ctx_list sysctl_ctx; + int msix_eqvec; }; enum { diff --git a/sys/dev/mlx5/mlx5_core/mlx5_main.c b/sys/dev/mlx5/mlx5_core/mlx5_main.c index d443433f67cf..df18c11121b3 100644 --- a/sys/dev/mlx5/mlx5_core/mlx5_main.c +++ b/sys/dev/mlx5/mlx5_core/mlx5_main.c @@ -61,10 +61,6 @@ static int prof_sel = MLX5_DEFAULT_PROF; module_param_named(prof_sel, prof_sel, int, 0444); MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2"); -static int mlx5_core_msix_eqvec; -module_param_named(msix_eqvec, mlx5_core_msix_eqvec, int, 0644); -MODULE_PARM_DESC(msix_eqvec, "Maximum number of MSIX event queue vectors"); - #define NUMA_NO_NODE -1 static LIST_HEAD(intf_list); @@ -243,7 +239,7 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev) struct mlx5_priv *priv = &dev->priv; struct mlx5_eq_table *table = &priv->eq_table; int num_eqs = 1 << MLX5_CAP_GEN(dev, log_max_eq); - int limit = mlx5_core_msix_eqvec; + int limit = dev->msix_eqvec; int nvec = MLX5_EQ_VEC_COMP_BASE; int i; @@ -1206,6 +1202,7 @@ static int init_one(struct pci_dev *pdev, { struct mlx5_core_dev *dev; struct mlx5_priv *priv; + device_t bsddev = pdev->dev.bsddev; int err; dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -1221,6 +1218,12 @@ static int init_one(struct pci_dev *pdev, dev->pdev = pdev; dev->event = mlx5_core_event; + sysctl_ctx_init(&dev->sysctl_ctx); + SYSCTL_ADD_INT(&dev->sysctl_ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(bsddev)), + OID_AUTO, "msix_eqvec", CTLFLAG_RDTUN, &dev->msix_eqvec, 0, + "Maximum number of MSIX event queue vectors, if set"); + INIT_LIST_HEAD(&priv->ctx_list); spin_lock_init(&priv->ctx_lock); mutex_init(&dev->pci_status_mutex); @@ -1256,6 +1259,7 @@ clean_health: close_pci: mlx5_pci_close(dev, priv); clean_dev: + sysctl_ctx_free(&dev->sysctl_ctx); kfree(dev); return err; } @@ -1276,6 +1280,7 @@ static void remove_one(struct pci_dev *pdev) mlx5_health_cleanup(dev); mlx5_pci_close(dev, priv); pci_set_drvdata(pdev, NULL); + sysctl_ctx_free(&dev->sysctl_ctx); kfree(dev); } diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h index f125313cd7b9..73f0268ca270 100644 --- a/sys/dev/mlx5/mlx5_en/en.h +++ b/sys/dev/mlx5/mlx5_en/en.h @@ -123,7 +123,8 @@ #define MLX5E_MAX_TX_MBUF_SIZE 65536 /* bytes */ #define MLX5E_MAX_TX_MBUF_FRAGS \ ((MLX5_SEND_WQE_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS) - \ - (MLX5E_MAX_TX_HEADER / MLX5_SEND_WQE_DS)) /* units */ + (MLX5E_MAX_TX_HEADER / MLX5_SEND_WQE_DS) - \ + 1 /* the maximum value of the DS counter is 0x3F and not 0x40 */) /* units */ #define MLX5E_MAX_TX_INLINE \ (MLX5E_MAX_TX_HEADER - sizeof(struct mlx5e_tx_wqe) + \ sizeof(((struct mlx5e_tx_wqe *)0)->eth.inline_hdr_start)) /* bytes */ @@ -453,6 +454,7 @@ struct mlx5e_params { u32 rx_priority_flow_control __aligned(4); u16 tx_max_inline; u8 tx_min_inline_mode; + u8 channels_rsss; }; #define MLX5E_PARAMS(m) \ @@ -461,6 +463,7 @@ struct mlx5e_params { m(+1, u64 tx_queue_size, "tx_queue_size", "Default send queue size") \ m(+1, u64 rx_queue_size, "rx_queue_size", "Default receive queue size") \ m(+1, u64 channels, "channels", "Default number of channels") \ + m(+1, u64 channels_rsss, "channels_rsss", "Default channels receive side scaling stride") \ m(+1, u64 coalesce_usecs_max, "coalesce_usecs_max", "Maximum usecs for joining packets") \ m(+1, u64 coalesce_pkts_max, "coalesce_pkts_max", "Maximum packets to join") \ m(+1, u64 rx_coalesce_usecs, "rx_coalesce_usecs", "Limit in usec for joining rx packets") \ diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c b/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c index d85afb570872..85b1fe85617f 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c @@ -493,6 +493,24 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) mlx5e_open_locked(priv->ifp); break; + case MLX5_PARAM_OFFSET(channels_rsss): + /* network interface must be down */ + if (was_opened) + mlx5e_close_locked(priv->ifp); + + /* import number of channels */ + if (priv->params_ethtool.channels_rsss < 1) + priv->params_ethtool.channels_rsss = 1; + else if (priv->params_ethtool.channels_rsss > 128) + priv->params_ethtool.channels_rsss = 128; + + priv->params.channels_rsss = priv->params_ethtool.channels_rsss; + + /* restart network interface, if any */ + if (was_opened) + mlx5e_open_locked(priv->ifp); + break; + case MLX5_PARAM_OFFSET(channels): /* network interface must be down */ if (was_opened) @@ -1041,6 +1059,7 @@ mlx5e_create_ethtool(struct mlx5e_priv *priv) priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; priv->params_ethtool.channels = priv->params.num_channels; + priv->params_ethtool.channels_rsss = priv->params.channels_rsss; priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c index 08a0e98fa0fb..916ebe72c46c 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c @@ -2204,14 +2204,16 @@ mlx5e_open_rqt(struct mlx5e_priv *priv) MLX5_SET(rqtc, rqtc, rqt_max_size, sz); for (i = 0; i < sz; i++) { - int ix; + int ix = i; #ifdef RSS - ix = rss_get_indirection_to_bucket(i); -#else - ix = i; + ix = rss_get_indirection_to_bucket(ix); #endif /* ensure we don't overflow */ ix %= priv->params.num_channels; + + /* apply receive side scaling stride, if any */ + ix -= ix % (int)priv->params.channels_rsss; + MLX5_SET(rqtc, rqtc, rq_num[i], priv->channel[ix]->rq.rqn); } @@ -3083,6 +3085,7 @@ mlx5e_build_ifp_priv(struct mlx5_core_dev *mdev, priv->mdev = mdev; priv->params.num_channels = num_comp_vectors; + priv->params.channels_rsss = 1; priv->order_base_2_num_channels = order_base_2(num_comp_vectors); priv->queue_mapping_channel_mask = roundup_pow_of_two(num_comp_vectors) - 1; diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c index 71dca59e795a..40d8157c6771 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c @@ -528,13 +528,11 @@ mlx5e_xmit_locked(struct ifnet *ifp, struct mlx5e_sq *sq, struct mbuf *mb) /* Process the queue */ while ((next = drbr_peek(ifp, sq->br)) != NULL) { if (mlx5e_sq_xmit(sq, &next) != 0) { - if (next == NULL) { - drbr_advance(ifp, sq->br); - } else { + if (next != NULL) { drbr_putback(ifp, sq->br, next); atomic_store_rel_int(&sq->queue_state, MLX5E_SQ_FULL); + break; } - break; } drbr_advance(ifp, sq->br); } diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c index d07a914a00cc..cf5cacbf0fe6 100644 --- a/sys/dev/mmc/mmc.c +++ b/sys/dev/mmc/mmc.c @@ -1591,6 +1591,7 @@ mmc_discover_cards(struct mmc_softc *sc) int err, host_caps, i, newcard; uint32_t resp, sec_count, status; uint16_t rca = 2; + int16_t rev; uint8_t card_type; host_caps = mmcbr_get_caps(sc->dev); @@ -1779,6 +1780,7 @@ mmc_discover_cards(struct mmc_softc *sc) goto free_ivar; } + rev = -1; /* Only MMC >= 4.x devices support EXT_CSD. */ if (ivar->csd.spec_vers >= 4) { err = mmc_send_ext_csd(sc->dev, sc->dev, @@ -1789,6 +1791,7 @@ mmc_discover_cards(struct mmc_softc *sc) goto free_ivar; } ext_csd = ivar->raw_ext_csd; + rev = ext_csd[EXT_CSD_REV]; /* Handle extended capacity from EXT_CSD */ sec_count = le32dec(&ext_csd[EXT_CSD_SEC_CNT]); if (sec_count != 0) { @@ -1859,7 +1862,7 @@ mmc_discover_cards(struct mmc_softc *sc) * units of 10 ms), defaulting to 500 ms. */ ivar->cmd6_time = 500 * 1000; - if (ext_csd[EXT_CSD_REV] >= 6) + if (rev >= 6) ivar->cmd6_time = 10 * ext_csd[EXT_CSD_GEN_CMD6_TIME]; /* Handle HC erase sector size. */ @@ -1880,8 +1883,7 @@ mmc_discover_cards(struct mmc_softc *sc) } } - mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid, - ext_csd[EXT_CSD_REV] >= 5); + mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid, rev >= 5); child_common: for (quirk = &mmc_quirks[0]; quirk->mid != 0x0; quirk++) { diff --git a/sys/dev/pci/pci_user.c b/sys/dev/pci/pci_user.c index 4053e193b012..4e40a8167362 100644 --- a/sys/dev/pci/pci_user.c +++ b/sys/dev/pci/pci_user.c @@ -446,6 +446,14 @@ pci_conf_match(u_long cmd, struct pci_match_conf *matches, int num_matches, } } +/* + * Like PVE_NEXT but takes an explicit length since 'pve' is a user + * pointer that cannot be dereferenced. + */ +#define PVE_NEXT_LEN(pve, datalen) \ + ((struct pci_vpd_element *)((char *)(pve) + \ + sizeof(struct pci_vpd_element) + (datalen))) + static int pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio) { @@ -494,7 +502,7 @@ pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio) strlen(vpd->vpd_ident)); if (error) return (error); - vpd_user = PVE_NEXT(vpd_user); + vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen); vpd_element.pve_flags = 0; for (i = 0; i < vpd->vpd_rocnt; i++) { vpd_element.pve_keyword[0] = vpd->vpd_ros[i].keyword[0]; @@ -507,7 +515,7 @@ pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio) vpd->vpd_ros[i].len); if (error) return (error); - vpd_user = PVE_NEXT(vpd_user); + vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen); } vpd_element.pve_flags = PVE_FLAG_RW; for (i = 0; i < vpd->vpd_wcnt; i++) { @@ -521,7 +529,7 @@ pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio) vpd->vpd_w[i].len); if (error) return (error); - vpd_user = PVE_NEXT(vpd_user); + vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen); } KASSERT((char *)vpd_user - (char *)lvio->plvi_data == len, ("length mismatch")); diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index c7bb97c3a0fe..94bd2f1a4147 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -156,6 +156,10 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock) error = tsleep(&random_alg_context, PCATCH, "randseed", hz/10); if (error == ERESTART || error == EINTR) break; + /* Squash tsleep timeout condition */ + if (error == EWOULDBLOCK) + error = 0; + KASSERT(error == 0, ("unexpected tsleep error %d", error)); } if (error == 0) { read_rate_increment((uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t)); @@ -184,9 +188,13 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock) * uninterruptible syscalls. */ if (error == 0 && uio->uio_resid != 0 && - total_read % sigchk_period == 0) + total_read % sigchk_period == 0) { error = tsleep_sbt(&random_alg_context, PCATCH, "randrd", SBT_1NS, 0, C_HARDCLOCK); + /* Squash tsleep timeout condition */ + if (error == EWOULDBLOCK) + error = 0; + } } if (error == ERESTART || error == EINTR) error = 0; diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index 2a3ce12ea63d..f117fb49c88d 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -1575,11 +1575,10 @@ sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data) #ifdef MMCCAM slot->ccb->mmcio.stop.opcode == MMC_STOP_TRANSMISSION && #else - slot->req->stop && + slot->req->stop != NULL && #endif !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP))) mode |= SDHCI_TRNS_ACMD12; - } if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c index 325106200320..7ccc9da533de 100644 --- a/sys/dev/sound/midi/midi.c +++ b/sys/dev/sound/midi/midi.c @@ -1467,18 +1467,14 @@ midi_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: retval = midi_load(); -#if 0 if (retval == 0) retval = seq_modevent(mod, type, data); -#endif break; case MOD_UNLOAD: retval = midi_unload(); -#if 0 if (retval == 0) retval = seq_modevent(mod, type, data); -#endif break; default: diff --git a/sys/dev/sound/pci/csamidi.c b/sys/dev/sound/pci/csamidi.c new file mode 100644 index 000000000000..21543e736e9f --- /dev/null +++ b/sys/dev/sound/pci/csamidi.c @@ -0,0 +1,290 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + + * Copyright (c) 2015-2018 Tai-hwa Liang <avatar@FreeBSD.org> + * All rights reserved + * + * 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 <sys/param.h> +#include <sys/types.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <sys/systm.h> +#include <sys/kobj.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include "opt_snd.h" +#endif + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <dev/sound/chip.h> +#include <dev/sound/pcm/sound.h> + +#include <dev/sound/midi/midi.h> +#include <dev/sound/midi/mpu401.h> + +#include <dev/sound/pci/csareg.h> +#include <dev/sound/pci/csavar.h> + +#include "mpufoi_if.h" + +SND_DECLARE_FILE("$FreeBSD$"); + +/* pulled from mpu401.c */ +#define MPU_DATAPORT 0 +#define MPU_CMDPORT 1 +#define MPU_STATPORT 1 +#define MPU_RESET 0xff +#define MPU_UART 0x3f +#define MPU_ACK 0xfe +#define MPU_STATMASK 0xc0 +#define MPU_OUTPUTBUSY 0x40 +#define MPU_INPUTBUSY 0x80 + +/* device private data */ +struct csa_midi_softc { + /* hardware resources */ + int io_rid; /* io rid */ + struct resource *io; /* io */ + + struct mtx mtx; + device_t dev; + struct mpu401 *mpu; + mpu401_intr_t *mpu_intr; + int mflags; /* MIDI flags */ +}; + +static struct kobj_class csamidi_mpu_class; +static devclass_t midicsa_devclass; + +static u_int32_t +csamidi_readio(struct csa_midi_softc *scp, u_long offset) +{ + if (offset < BA0_AC97_RESET) + return bus_space_read_4(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), offset) & 0xffffffff; + else + return (0); +} + +static void +csamidi_writeio(struct csa_midi_softc *scp, u_long offset, u_int32_t data) +{ + if (offset < BA0_AC97_RESET) + bus_space_write_4(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), offset, data); +} + +static void +csamidi_midi_intr(void *arg) +{ + struct csa_midi_softc *scp = (struct csa_midi_softc *)arg; + + if (scp->mpu_intr) + (scp->mpu_intr)(scp->mpu); +} + +static unsigned char +csamidi_mread(struct mpu401 *arg __unused, void *cookie, int reg) +{ + struct csa_midi_softc *scp = cookie; + unsigned int rc; + unsigned int uart_stat; + + rc = 0; + /* hacks to convert hardware status to MPU compatible ones */ + switch (reg) { + case MPU_STATPORT: + uart_stat = csamidi_readio(scp, BA0_MIDSR); + if (uart_stat & MIDSR_TBF) + rc |= MPU_OUTPUTBUSY; /* Tx buffer full */ + if (uart_stat & MIDSR_RBE) + rc |= MPU_INPUTBUSY; + break; + case MPU_DATAPORT: + rc = csamidi_readio(scp, BA0_MIDRP); + break; + default: + printf("csamidi_mread: unknown register %d\n", reg); + break; + } + return (rc); +} + +static void +csamidi_mwrite(struct mpu401 *arg __unused, void *cookie, int reg, unsigned char b) +{ + struct csa_midi_softc *scp = cookie; + unsigned int val; + + switch (reg) { + case MPU_CMDPORT: + switch (b) + { + case MPU_RESET: + /* preserve current operation mode */ + val = csamidi_readio(scp, BA0_MIDCR); + /* reset the MIDI port */ + csamidi_writeio(scp, BA0_MIDCR, MIDCR_MRST); + csamidi_writeio(scp, BA0_MIDCR, MIDCR_MLB); + csamidi_writeio(scp, BA0_MIDCR, 0x00); + /* restore previous operation mode */ + csamidi_writeio(scp, BA0_MIDCR, val); + break; + case MPU_UART: + /* switch to UART mode, no-op */ + default: + break; + } + break; + case MPU_DATAPORT: + /* put the MIDI databyte in the write port */ + csamidi_writeio(scp, BA0_MIDWP, b); + break; + default: + printf("csamidi_mwrite: unknown register %d\n", reg); + break; + } +} + +static int +csamidi_muninit(struct mpu401 *arg __unused, void *cookie) +{ + struct csa_midi_softc *scp = cookie; + + mtx_lock(&scp->mtx); + scp->mpu_intr = NULL; + mtx_unlock(&scp->mtx); + + return (0); +} + +static int +midicsa_probe(device_t dev) +{ + struct sndcard_func *func; + + /* The parent device has already been probed. */ + + func = device_get_ivars(dev); + if (func == NULL || func->func != SCF_MIDI) + return (ENXIO); + + device_set_desc(dev, "CS461x MIDI"); + return (0); +} + +static int +midicsa_attach(device_t dev) +{ + struct csa_midi_softc *scp; + struct sndcard_func *func; + int rc = ENXIO; + + scp = device_get_softc(dev); + func = device_get_ivars(dev); + + bzero(scp, sizeof(struct csa_midi_softc)); + scp->dev = dev; + + /* allocate the required resources */ + scp->io_rid = PCIR_BAR(0); + scp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &scp->io_rid, RF_ACTIVE); + if (scp->io == NULL) + goto err0; + + /* init the fake MPU401 interface. */ + scp->mpu = mpu401_init(&csamidi_mpu_class, scp, csamidi_midi_intr, + &scp->mpu_intr); + if (scp->mpu == NULL) { + rc = ENOMEM; + goto err1; + } + + mtx_init(&scp->mtx, device_get_nameunit(dev), "csamidi softc", + MTX_DEF); + + /* reset the MIDI port */ + csamidi_writeio(scp, BA0_MIDCR, MIDCR_MRST); + /* MIDI transmit enable, no interrupt */ + csamidi_writeio(scp, BA0_MIDCR, MIDCR_TXE | MIDCR_RXE); + csamidi_writeio(scp, BA0_HICR, HICR_IEV | HICR_CHGM); + + return (0); +err1: + bus_release_resource(dev, SYS_RES_MEMORY, scp->io_rid, scp->io); + scp->io = NULL; +err0: + return (rc); +} + +static int +midicsa_detach(device_t dev) +{ + struct csa_midi_softc *scp; + int rc = 0; + + scp = device_get_softc(dev); + rc = mpu401_uninit(scp->mpu); + if (rc) + return (rc); + if (scp->io != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, scp->io_rid, + scp->io); + scp->io = NULL; + } + mtx_destroy(&scp->mtx); + return (rc); +} + +static kobj_method_t csamidi_mpu_methods[] = { + KOBJMETHOD(mpufoi_read, csamidi_mread), + KOBJMETHOD(mpufoi_write, csamidi_mwrite), + KOBJMETHOD(mpufoi_uninit, csamidi_muninit), + KOBJMETHOD_END +}; + +static DEFINE_CLASS(csamidi_mpu, csamidi_mpu_methods, 0); + +static device_method_t midicsa_methods[] = { + DEVMETHOD(device_probe, midicsa_probe), + DEVMETHOD(device_attach, midicsa_attach), + DEVMETHOD(device_detach, midicsa_detach), + + DEVMETHOD_END +}; + +static driver_t midicsa_driver = { + "midi", + midicsa_methods, + sizeof(struct csa_midi_softc), +}; +DRIVER_MODULE(snd_csa_midi, csa, midicsa_driver, midicsa_devclass, 0, 0); +MODULE_DEPEND(snd_csa_midi, snd_csa, 1, 1, 1); +MODULE_DEPEND(snd_csa_midi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); +MODULE_VERSION(snd_csa_midi, 1); diff --git a/sys/dev/usb/input/wmt.c b/sys/dev/usb/input/wmt.c index 226023a57bfd..c5b774244ece 100644 --- a/sys/dev/usb/input/wmt.c +++ b/sys/dev/usb/input/wmt.c @@ -521,7 +521,7 @@ tr_ignore: case USB_ST_SETUP: tr_setup: - usbd_xfer_set_frame_len(xfer, 0, sc->isize); + usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); usbd_transfer_submit(xfer); break; default: diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index f3c68c408bb7..d8a3796f91de 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -421,81 +421,8 @@ initclocks(void *dummy) #endif } -/* - * Each time the real-time timer fires, this function is called on all CPUs. - * Note that hardclock() calls hardclock_cpu() for the boot CPU, so only - * the other CPUs in the system need to call this function. - */ void -hardclock_cpu(int usermode) -{ - struct pstats *pstats; - struct thread *td = curthread; - struct proc *p = td->td_proc; - int flags; - - /* - * Run current process's virtual and profile time, as needed. - */ - pstats = p->p_stats; - flags = 0; - if (usermode && - timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value)) { - PROC_ITIMLOCK(p); - if (itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) - flags |= TDF_ALRMPEND | TDF_ASTPENDING; - PROC_ITIMUNLOCK(p); - } - if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value)) { - PROC_ITIMLOCK(p); - if (itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) - flags |= TDF_PROFPEND | TDF_ASTPENDING; - PROC_ITIMUNLOCK(p); - } - thread_lock(td); - td->td_flags |= flags; - thread_unlock(td); - -#ifdef HWPMC_HOOKS - if (PMC_CPU_HAS_SAMPLES(PCPU_GET(cpuid))) - PMC_CALL_HOOK_UNLOCKED(curthread, PMC_FN_DO_SAMPLES, NULL); - if (td->td_intr_frame != NULL) - PMC_SOFT_CALL_TF( , , clock, hard, td->td_intr_frame); -#endif - callout_process(sbinuptime()); - if (__predict_false(DPCPU_GET(epoch_cb_count))) - GROUPTASK_ENQUEUE(DPCPU_PTR(epoch_cb_task)); -} - -/* - * The real-time timer, interrupting hz times per second. - */ -void -hardclock(int usermode, uintfptr_t pc) -{ - - atomic_add_int(&ticks, 1); - hardclock_cpu(usermode); - tc_ticktock(1); - cpu_tick_calibration(); - /* - * If no separate statistics clock is available, run it from here. - * - * XXX: this only works for UP - */ - if (stathz == 0) { - profclock(usermode, pc); - statclock(usermode); - } -#ifdef DEVICE_POLLING - hardclock_device_poll(); /* this is very short and quick */ -#endif /* DEVICE_POLLING */ - if (watchdog_enabled > 0 && --watchdog_ticks <= 0) - watchdog_fire(); -} - -void -hardclock_cnt(int cnt, int usermode) +hardclock(int cnt, int usermode) { struct pstats *pstats; struct thread *td = curthread; @@ -696,14 +623,7 @@ stopprofclock(struct proc *p) * This should be called by all active processors. */ void -statclock(int usermode) -{ - - statclock_cnt(1, usermode); -} - -void -statclock_cnt(int cnt, int usermode) +statclock(int cnt, int usermode) { struct rusage *ru; struct vmspace *vm; @@ -776,14 +696,7 @@ statclock_cnt(int cnt, int usermode) } void -profclock(int usermode, uintfptr_t pc) -{ - - profclock_cnt(1, usermode, pc); -} - -void -profclock_cnt(int cnt, int usermode, uintfptr_t pc) +profclock(int cnt, int usermode, uintfptr_t pc) { struct thread *td; #ifdef GPROF diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c index ed7b67f62cf6..dfc9081ba9f6 100644 --- a/sys/kern/kern_clocksource.c +++ b/sys/kern/kern_clocksource.c @@ -183,7 +183,7 @@ handleevents(sbintime_t now, int fake) hct = DPCPU_PTR(hardclocktime); *hct = state->nexthard - tick_sbt; if (fake < 2) { - hardclock_cnt(runs, usermode); + hardclock(runs, usermode); done = 1; } } @@ -193,7 +193,7 @@ handleevents(sbintime_t now, int fake) runs++; } if (runs && fake < 2) { - statclock_cnt(runs, usermode); + statclock(runs, usermode); done = 1; } if (profiling) { @@ -203,7 +203,7 @@ handleevents(sbintime_t now, int fake) runs++; } if (runs && !fake) { - profclock_cnt(runs, usermode, TRAPF_PC(frame)); + profclock(runs, usermode, TRAPF_PC(frame)); done = 1; } } else diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 79b34dc76499..b60c2d5b40ef 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -83,7 +83,7 @@ _Static_assert(offsetof(struct thread, td_pflags) == 0x104, "struct thread KBI td_pflags"); _Static_assert(offsetof(struct thread, td_frame) == 0x470, "struct thread KBI td_frame"); -_Static_assert(offsetof(struct thread, td_emuldata) == 0x518, +_Static_assert(offsetof(struct thread, td_emuldata) == 0x528, "struct thread KBI td_emuldata"); _Static_assert(offsetof(struct proc, p_flag) == 0xb0, "struct proc KBI p_flag"); diff --git a/sys/kern/subr_blist.c b/sys/kern/subr_blist.c index d77d12997a57..db7df6932633 100644 --- a/sys/kern/subr_blist.c +++ b/sys/kern/subr_blist.c @@ -224,17 +224,19 @@ blist_create(daddr_t blocks, int flags) u_daddr_t nodes, radix, skip; int digit; + if (blocks == 0) + panic("invalid block count"); + /* - * Calculate the radix and node count used for scanning. Find the last - * block that is followed by a terminator. + * Calculate the radix and node count used for scanning. */ last_block = blocks - 1; radix = BLIST_BMAP_RADIX; while (radix < blocks) { if (((last_block / radix + 1) & BLIST_META_MASK) != 0) /* - * A terminator will be added. Update last_block to the - * position just before that terminator. + * We must widen the blist to avoid partially + * filled nodes. */ last_block |= radix - 1; radix *= BLIST_META_RADIX; @@ -244,7 +246,9 @@ blist_create(daddr_t blocks, int flags) * Count the meta-nodes in the expanded tree, including the final * terminator, from the bottom level up to the root. */ - nodes = (last_block >= blocks) ? 2 : 1; + nodes = 1; + if (radix - blocks >= BLIST_BMAP_RADIX) + nodes++; last_block /= BLIST_BMAP_RADIX; while (last_block > 0) { nodes += last_block + 1; diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c index 82c276f210a2..1c3a9804694c 100644 --- a/sys/kern/subr_rtc.c +++ b/sys/kern/subr_rtc.c @@ -138,6 +138,7 @@ settime_task_func(void *arg, int pending) { struct timespec ts; struct rtc_instance *rtc; + int error; rtc = arg; if (!(rtc->flags & CLOCKF_SETTIME_NO_TS)) { @@ -150,7 +151,9 @@ settime_task_func(void *arg, int pending) ts.tv_sec = 0; ts.tv_nsec = 0; } - CLOCK_SETTIME(rtc->clockdev, &ts); + error = CLOCK_SETTIME(rtc->clockdev, &ts); + if (error != 0 && bootverbose) + device_printf(rtc->clockdev, "CLOCK_SETTIME error %d\n", error); } static void diff --git a/sys/mips/conf/MALTA64EL b/sys/mips/conf/MALTA64EL index 5b87b6e171f4..34df1da7146c 100644 --- a/sys/mips/conf/MALTA64EL +++ b/sys/mips/conf/MALTA64EL @@ -9,5 +9,4 @@ include "std.MALTA" machine mips mips64el makeoptions ARCH_FLAGS="-march=mips64 -mabi=64" -makeoptions MODULES_OVERRIDE="" makeoptions KERNLOADADDR=0xffffffff80100000 diff --git a/sys/modules/dtb/omap4/Makefile b/sys/modules/dtb/omap4/Makefile index a6eb8e20de7a..8e6ea876bbe7 100644 --- a/sys/modules/dtb/omap4/Makefile +++ b/sys/modules/dtb/omap4/Makefile @@ -5,4 +5,8 @@ DTS= \ pandaboard.dts \ pandaboard-es.dts +LINKS= \ + ${DTBDIR}/pandaboard.dtb ${DTBDIR}/omap4-panda.dtb \ + ${DTBDIR}/pandaboard-es.dtb ${DTBDIR}/omap4-panda-es.dtb + .include <bsd.dtb.mk> diff --git a/sys/modules/efirt/Makefile b/sys/modules/efirt/Makefile index 2613150db489..2e53336cf22d 100644 --- a/sys/modules/efirt/Makefile +++ b/sys/modules/efirt/Makefile @@ -8,4 +8,11 @@ SRCS= efirt.c efirt_machdep.c efidev.c SRCS+= efirtc.c SRCS+= device_if.h bus_if.h clock_if.h +.if ${MACHINE_CPUARCH} == "amd64" +SRCS+= efirt_support.S +efirt_support.o: efirt_support.S assym.inc + ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ + ${.IMPSRC} -o ${.TARGET} +.endif + .include <bsd.kmod.mk> diff --git a/sys/modules/sound/driver/csa/Makefile b/sys/modules/sound/driver/csa/Makefile index af02ef4f4e0d..b1a3f1fb9df4 100644 --- a/sys/modules/sound/driver/csa/Makefile +++ b/sys/modules/sound/driver/csa/Makefile @@ -3,7 +3,7 @@ .PATH: ${SRCTOP}/sys/dev/sound/pci KMOD= snd_csa -SRCS= device_if.h bus_if.h pci_if.h -SRCS+= csa.c csapcm.c +SRCS= device_if.h bus_if.h mpufoi_if.h pci_if.h +SRCS+= csa.c csamidi.c csapcm.c .include <bsd.kmod.mk> diff --git a/sys/net/iflib.c b/sys/net/iflib.c index faee06d02a83..65bf07a0b2c1 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -641,7 +641,6 @@ SYSCTL_INT(_net_iflib, OID_AUTO, fl_refills_large, CTLFLAG_RD, static int iflib_txq_drain_flushing; static int iflib_txq_drain_oactive; static int iflib_txq_drain_notready; -static int iflib_txq_drain_encapfail; SYSCTL_INT(_net_iflib, OID_AUTO, txq_drain_flushing, CTLFLAG_RD, &iflib_txq_drain_flushing, 0, "# drain flushes"); @@ -649,8 +648,6 @@ SYSCTL_INT(_net_iflib, OID_AUTO, txq_drain_oactive, CTLFLAG_RD, &iflib_txq_drain_oactive, 0, "# drain oactives"); SYSCTL_INT(_net_iflib, OID_AUTO, txq_drain_notready, CTLFLAG_RD, &iflib_txq_drain_notready, 0, "# drain notready"); -SYSCTL_INT(_net_iflib, OID_AUTO, txq_drain_encapfail, CTLFLAG_RD, - &iflib_txq_drain_encapfail, 0, "# drain encap fails"); static int iflib_encap_load_mbuf_fail; @@ -670,21 +667,14 @@ SYSCTL_INT(_net_iflib, OID_AUTO, encap_txd_encap_fail, CTLFLAG_RD, static int iflib_task_fn_rxs; static int iflib_rx_intr_enables; static int iflib_fast_intrs; -static int iflib_intr_link; -static int iflib_intr_msix; static int iflib_rx_unavail; static int iflib_rx_ctx_inactive; -static int iflib_rx_zero_len; static int iflib_rx_if_input; static int iflib_rx_mbuf_null; static int iflib_rxd_flush; static int iflib_verbose_debug; -SYSCTL_INT(_net_iflib, OID_AUTO, intr_link, CTLFLAG_RD, - &iflib_intr_link, 0, "# intr link calls"); -SYSCTL_INT(_net_iflib, OID_AUTO, intr_msix, CTLFLAG_RD, - &iflib_intr_msix, 0, "# intr msix calls"); SYSCTL_INT(_net_iflib, OID_AUTO, task_fn_rx, CTLFLAG_RD, &iflib_task_fn_rxs, 0, "# task_fn_rx calls"); SYSCTL_INT(_net_iflib, OID_AUTO, rx_intr_enables, CTLFLAG_RD, @@ -695,8 +685,6 @@ SYSCTL_INT(_net_iflib, OID_AUTO, rx_unavail, CTLFLAG_RD, &iflib_rx_unavail, 0, "# times rxeof called with no available data"); SYSCTL_INT(_net_iflib, OID_AUTO, rx_ctx_inactive, CTLFLAG_RD, &iflib_rx_ctx_inactive, 0, "# times rxeof called with inactive context"); -SYSCTL_INT(_net_iflib, OID_AUTO, rx_zero_len, CTLFLAG_RD, - &iflib_rx_zero_len, 0, "# times rxeof saw zero len mbuf"); SYSCTL_INT(_net_iflib, OID_AUTO, rx_if_input, CTLFLAG_RD, &iflib_rx_if_input, 0, "# times rxeof called if_input"); SYSCTL_INT(_net_iflib, OID_AUTO, rx_mbuf_null, CTLFLAG_RD, @@ -713,12 +701,12 @@ iflib_debug_reset(void) iflib_tx_seen = iflib_tx_sent = iflib_tx_encap = iflib_rx_allocs = iflib_fl_refills = iflib_fl_refills_large = iflib_tx_frees = iflib_txq_drain_flushing = iflib_txq_drain_oactive = - iflib_txq_drain_notready = iflib_txq_drain_encapfail = + iflib_txq_drain_notready = iflib_encap_load_mbuf_fail = iflib_encap_pad_mbuf_fail = iflib_encap_txq_avail_fail = iflib_encap_txd_encap_fail = iflib_task_fn_rxs = iflib_rx_intr_enables = iflib_fast_intrs = - iflib_intr_link = iflib_intr_msix = iflib_rx_unavail = - iflib_rx_ctx_inactive = iflib_rx_zero_len = iflib_rx_if_input = + iflib_rx_unavail = + iflib_rx_ctx_inactive = iflib_rx_if_input = iflib_rx_mbuf_null = iflib_rxd_flush = 0; } @@ -839,6 +827,9 @@ netmap_fl_refill(iflib_rxq_t rxq, struct netmap_kring *kring, uint32_t nm_i, boo if_ctx_t ctx = rxq->ifr_ctx; iflib_fl_t fl = &rxq->ifr_fl[0]; uint32_t refill_pidx, nic_i; +#if IFLIB_DEBUG_COUNTERS + int rf_count = 0; +#endif if (nm_i == head && __predict_true(!init)) return 0; @@ -851,7 +842,12 @@ netmap_fl_refill(iflib_rxq_t rxq, struct netmap_kring *kring, uint32_t nm_i, boo */ head = nm_prev(head, lim); nic_i = UINT_MAX; + DBG_COUNTER_INC(fl_refills); while (nm_i != head) { +#if IFLIB_DEBUG_COUNTERS + if (++rf_count == 9) + DBG_COUNTER_INC(fl_refills_large); +#endif for (int tmp_pidx = 0; tmp_pidx < IFLIB_MAX_RX_REFRESH && nm_i != head; tmp_pidx++) { struct netmap_slot *slot = &ring->slot[nm_i]; void *addr = PNMB(na, slot, &fl->ifl_bus_addrs[tmp_pidx]); @@ -898,8 +894,10 @@ netmap_fl_refill(iflib_rxq_t rxq, struct netmap_kring *kring, uint32_t nm_i, boo if (map) bus_dmamap_sync(fl->ifl_ifdi->idi_tag, fl->ifl_ifdi->idi_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - if (__predict_true(nic_i != UINT_MAX)) + if (__predict_true(nic_i != UINT_MAX)) { ctx->isc_rxd_flush(ctx->ifc_softc, rxq->ifr_id, fl->ifl_id, nic_i); + DBG_COUNTER_INC(rxd_flush); + } return (0); } @@ -998,6 +996,7 @@ iflib_netmap_txsync(struct netmap_kring *kring, int flags) /* Fill the slot in the NIC ring. */ ctx->isc_txd_encap(ctx->ifc_softc, &pi); + DBG_COUNTER_INC(tx_encap); /* prefetch for next round */ __builtin_prefetch(&ring->slot[nm_i + 1]); @@ -1524,8 +1523,10 @@ iflib_fast_intr_rxtx(void *arg) cidx = rxq->ifr_fl[0].ifl_cidx; if (iflib_rxd_avail(ctx, rxq, cidx, 1)) GROUPTASK_ENQUEUE(gtask); - else + else { IFDI_RX_QUEUE_INTR_ENABLE(ctx, rxq->ifr_id); + DBG_COUNTER_INC(rx_intr_enables); + } return (FILTER_HANDLED); } @@ -2887,6 +2888,7 @@ iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) return (ENOMEM); } else { m_freem(*mp); + DBG_COUNTER_INC(tx_frees); *mp = m; } } @@ -2994,6 +2996,7 @@ iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) pi->ipi_ip_hlen = sizeof(struct ip6_hdr); if (__predict_false(m->m_len < pi->ipi_ehdrlen + sizeof(struct ip6_hdr))) { + txq->ift_pullups++; if (__predict_false((m = m_pullup(m, pi->ipi_ehdrlen + sizeof(struct ip6_hdr))) == NULL)) return (ENOMEM); } @@ -3041,34 +3044,6 @@ iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) return (0); } -static __noinline struct mbuf * -collapse_pkthdr(struct mbuf *m0) -{ - struct mbuf *m, *m_next, *tmp; - - m = m0; - m_next = m->m_next; - while (m_next != NULL && m_next->m_len == 0) { - m = m_next; - m->m_next = NULL; - m_free(m); - m_next = m_next->m_next; - } - m = m0; - m->m_next = m_next; - if (m_next == NULL) - return (m); - if ((m_next->m_flags & M_EXT) == 0) { - m = m_defrag(m, M_NOWAIT); - } else { - tmp = m_next->m_next; - memcpy(m_next, m, MPKTHSIZE); - m = m_next; - m->m_next = tmp; - } - return (m); -} - /* * If dodgy hardware rejects the scatter gather chain we've handed it * we'll need to remove the mbuf chain from ifsg_m[] before we can add the @@ -3117,8 +3092,7 @@ iflib_busdma_load_mbuf_sg(iflib_txq_t txq, bus_dma_tag_t tag, bus_dmamap_t map, /* * Please don't ever do this */ - if (__predict_false(m->m_len == 0)) - *m0 = collapse_pkthdr(m); + MPASS(__predict_true(m->m_len > 0)); ctx = txq->ift_ctx; sctx = ctx->ifc_sctx; @@ -3259,6 +3233,7 @@ iflib_ether_pad(device_t dev, struct mbuf **m_head, uint16_t min_frame_size) m_freem(*m_head); device_printf(dev, "cannot pad short frame, m_dup() failed"); DBG_COUNTER_INC(encap_pad_mbuf_fail); + DBG_COUNTER_INC(tx_frees); return ENOMEM; } m_freem(*m_head); @@ -3274,6 +3249,7 @@ iflib_ether_pad(device_t dev, struct mbuf **m_head, uint16_t min_frame_size) m_freem(*m_head); device_printf(dev, "cannot pad short frame\n"); DBG_COUNTER_INC(encap_pad_mbuf_fail); + DBG_COUNTER_INC(tx_frees); return (ENOBUFS); } @@ -3337,8 +3313,10 @@ iflib_encap(iflib_txq_t txq, struct mbuf **m_headp) if ((sctx->isc_flags & IFLIB_NEED_ETHER_PAD) && __predict_false(m_head->m_pkthdr.len < scctx->isc_min_frame_size)) { err = iflib_ether_pad(ctx->ifc_dev, m_headp, scctx->isc_min_frame_size); - if (err) + if (err) { + DBG_COUNTER_INC(encap_txd_encap_fail); return err; + } } m_head = *m_headp; @@ -3352,8 +3330,10 @@ iflib_encap(iflib_txq_t txq, struct mbuf **m_headp) /* deliberate bitwise OR to make one condition */ if (__predict_true((pi.ipi_csum_flags | pi.ipi_vtag))) { - if (__predict_false((err = iflib_parse_header(txq, &pi, m_headp)) != 0)) + if (__predict_false((err = iflib_parse_header(txq, &pi, m_headp)) != 0)) { + DBG_COUNTER_INC(encap_txd_encap_fail); return (err); + } m_head = *m_headp; } @@ -3370,12 +3350,13 @@ defrag: if (m_head == NULL) remap++; } - if (remap == 1) + if (remap == 1) { + txq->ift_mbuf_defrag++; m_head = m_defrag(*m_headp, M_NOWAIT); + } remap++; if (__predict_false(m_head == NULL)) goto defrag_failed; - txq->ift_mbuf_defrag++; *m_headp = m_head; goto retry; break; @@ -3391,6 +3372,7 @@ defrag: } txq->ift_map_failed++; DBG_COUNTER_INC(encap_load_mbuf_fail); + DBG_COUNTER_INC(encap_txd_encap_fail); return (err); } @@ -3404,6 +3386,7 @@ defrag: if (map != NULL) bus_dmamap_unload(desc_tag, map); DBG_COUNTER_INC(encap_txq_avail_fail); + DBG_COUNTER_INC(encap_txd_encap_fail); if ((txq->ift_task.gt_task.ta_flags & TASK_ENQUEUED) == 0) GROUPTASK_ENQUEUE(&txq->ift_task); return (ENOBUFS); @@ -3466,9 +3449,12 @@ defrag: goto defrag; } } - DBG_COUNTER_INC(encap_txd_encap_fail); goto defrag_failed; } + /* + * err can't possibly be non-zero here, so we don't neet to test it + * to see if we need to DBG_COUNTER_INC(encap_txd_encap_fail). + */ return (err); defrag_failed: @@ -3477,6 +3463,7 @@ defrag_failed: m_freem(*m_headp); DBG_COUNTER_INC(tx_frees); *m_headp = NULL; + DBG_COUNTER_INC(encap_txd_encap_fail); return (ENOMEM); } @@ -3676,12 +3663,10 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) in_use_prev = txq->ift_in_use; err = iflib_encap(txq, mp); if (__predict_false(err)) { - DBG_COUNTER_INC(txq_drain_encapfail); /* no room - bail out */ if (err == ENOBUFS) break; consumed++; - DBG_COUNTER_INC(txq_drain_encapfail); /* we can't send this packet - skip it */ continue; } @@ -3741,6 +3726,7 @@ iflib_txq_drain_free(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) if (__predict_false(*mp == (struct mbuf *)txq)) continue; m_freem(*mp); + DBG_COUNTER_INC(tx_frees); } MPASS(ifmp_ring_is_stalled(r) == 0); return (avail); @@ -3987,6 +3973,7 @@ iflib_if_transmit(if_t ifp, struct mbuf *m) next = m->m_nextpkt; m->m_nextpkt = NULL; m_freem(m); + DBG_COUNTER_INC(tx_frees); m = next; } return (ENOBUFS); @@ -4029,6 +4016,7 @@ iflib_if_transmit(if_t ifp, struct mbuf *m) #endif ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE); m_freem(m); + DBG_COUNTER_INC(tx_frees); } return (err); diff --git a/sys/net/route.h b/sys/net/route.h index 28f1db01ef88..15ec1b3e9a38 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -410,10 +410,8 @@ struct rt_addrinfo { } while (0) #define RO_RTFREE(_ro) do { \ - if ((_ro)->ro_rt) { \ - RT_LOCK((_ro)->ro_rt); \ - RTFREE_LOCKED((_ro)->ro_rt); \ - } \ + if ((_ro)->ro_rt) \ + RTFREE((_ro)->ro_rt); \ } while (0) #define RO_INVALIDATE_CACHE(ro) do { \ diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c index e56cbc4d97cf..fedff49cfdc2 100644 --- a/sys/netinet/in_kdtrace.c +++ b/sys/netinet/in_kdtrace.c @@ -31,12 +31,16 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_sctp.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/sdt.h> SDT_PROVIDER_DEFINE(ip); +#ifdef SCTP SDT_PROVIDER_DEFINE(sctp); +#endif SDT_PROVIDER_DEFINE(tcp); SDT_PROVIDER_DEFINE(udp); SDT_PROVIDER_DEFINE(udplite); @@ -57,6 +61,7 @@ SDT_PROBE_DEFINE6_XLATE(ip, , , send, "struct ip *", "ipv4info_t *", "struct ip6_hdr *", "ipv6info_t *"); +#ifdef SCTP SDT_PROBE_DEFINE5_XLATE(sctp, , , receive, "void *", "pktinfo_t *", "struct sctp_tcb *", "csinfo_t *", @@ -78,6 +83,7 @@ SDT_PROBE_DEFINE6_XLATE(sctp, , , state__change, "struct sctp_tcb *", "sctpsinfo_t *", "void *", "void *", "int", "sctplsinfo_t *"); +#endif SDT_PROBE_DEFINE5_XLATE(tcp, , , accept__established, "void *", "pktinfo_t *", diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 98838fa041a1..671a9c7c7faf 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -235,16 +235,26 @@ in_pcblbgroup_alloc(struct inpcblbgrouphead *hdr, u_char vflag, grp->il_lport = port; grp->il_dependladdr = *addr; grp->il_inpsiz = size; - LIST_INSERT_HEAD(hdr, grp, il_list); + CK_LIST_INSERT_HEAD(hdr, grp, il_list); return (grp); } static void +in_pcblbgroup_free_deferred(epoch_context_t ctx) +{ + struct inpcblbgroup *grp; + + grp = __containerof(ctx, struct inpcblbgroup, il_epoch_ctx); + free(grp, M_PCB); +} + +static void in_pcblbgroup_free(struct inpcblbgroup *grp) { - LIST_REMOVE(grp, il_list); - free(grp, M_TEMP); + CK_LIST_REMOVE(grp, il_list); + epoch_call(net_epoch_preempt, &grp->il_epoch_ctx, + in_pcblbgroup_free_deferred); } static struct inpcblbgroup * @@ -301,13 +311,14 @@ in_pcblbgroup_reorder(struct inpcblbgrouphead *hdr, struct inpcblbgroup **grpp, static int in_pcbinslbgrouphash(struct inpcb *inp) { + const static struct timeval interval = { 60, 0 }; + static struct timeval lastprint; struct inpcbinfo *pcbinfo; struct inpcblbgrouphead *hdr; struct inpcblbgroup *grp; uint16_t hashmask, lport; uint32_t group_index; struct ucred *cred; - static int limit_logged = 0; pcbinfo = inp->inp_pcbinfo; @@ -346,7 +357,7 @@ in_pcbinslbgrouphash(struct inpcb *inp) hdr = &pcbinfo->ipi_lbgrouphashbase[ INP_PCBLBGROUP_PORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask)]; - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { if (grp->il_vflag == inp->inp_vflag && grp->il_lport == inp->inp_lport && memcmp(&grp->il_dependladdr, @@ -364,11 +375,9 @@ in_pcbinslbgrouphash(struct inpcb *inp) return (ENOBUFS); } else if (grp->il_inpcnt == grp->il_inpsiz) { if (grp->il_inpsiz >= INPCBLBGROUP_SIZMAX) { - if (!limit_logged) { - limit_logged = 1; + if (ratecheck(&lastprint, &interval)) printf("lb group port %d, limit reached\n", ntohs(grp->il_lport)); - } return (0); } @@ -410,7 +419,7 @@ in_pcbremlbgrouphash(struct inpcb *inp) INP_PCBLBGROUP_PORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask)]; - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { for (i = 0; i < grp->il_inpcnt; ++i) { if (grp->il_inp[i] != inp) continue; @@ -1950,18 +1959,18 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr, static struct inpcb * in_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, - const struct in_addr *laddr, uint16_t lport, const struct in_addr *faddr, - uint16_t fport, int lookupflags) + const struct in_addr *laddr, uint16_t lport, const struct in_addr *faddr, + uint16_t fport, int lookupflags) { - struct inpcb *local_wild = NULL; + struct inpcb *local_wild; const struct inpcblbgrouphead *hdr; struct inpcblbgroup *grp; - struct inpcblbgroup *grp_local_wild; + uint32_t idx; INP_HASH_LOCK_ASSERT(pcbinfo); - hdr = &pcbinfo->ipi_lbgrouphashbase[ - INP_PCBLBGROUP_PORTHASH(lport, pcbinfo->ipi_lbgrouphashmask)]; + hdr = &pcbinfo->ipi_lbgrouphashbase[INP_PCBLBGROUP_PORTHASH(lport, + pcbinfo->ipi_lbgrouphashmask)]; /* * Order of socket selection: @@ -1972,35 +1981,24 @@ in_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, * - Load balanced group does not contain jailed sockets * - Load balanced group does not contain IPv4 mapped INET6 wild sockets */ - LIST_FOREACH(grp, hdr, il_list) { + local_wild = NULL; + CK_LIST_FOREACH(grp, hdr, il_list) { #ifdef INET6 if (!(grp->il_vflag & INP_IPV4)) continue; #endif + if (grp->il_lport != lport) + continue; - if (grp->il_lport == lport) { - - uint32_t idx = 0; - int pkt_hash = INP_PCBLBGROUP_PKTHASH(faddr->s_addr, - lport, fport); - - idx = pkt_hash % grp->il_inpcnt; - - if (grp->il_laddr.s_addr == laddr->s_addr) { - return (grp->il_inp[idx]); - } else { - if (grp->il_laddr.s_addr == INADDR_ANY && - (lookupflags & INPLOOKUP_WILDCARD)) { - local_wild = grp->il_inp[idx]; - grp_local_wild = grp; - } - } - } + idx = INP_PCBLBGROUP_PKTHASH(faddr->s_addr, lport, fport) % + grp->il_inpcnt; + if (grp->il_laddr.s_addr == laddr->s_addr) + return (grp->il_inp[idx]); + if (grp->il_laddr.s_addr == INADDR_ANY && + (lookupflags & INPLOOKUP_WILDCARD) != 0) + local_wild = grp->il_inp[idx]; } - if (local_wild != NULL) { - return (local_wild); - } - return (NULL); + return (local_wild); } #ifdef PCBGROUP diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 31009099e6f7..86c9705cb905 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -70,6 +70,7 @@ */ CK_LIST_HEAD(inpcbhead, inpcb); CK_LIST_HEAD(inpcbporthead, inpcbport); +CK_LIST_HEAD(inpcblbgrouphead, inpcblbgroup); typedef uint64_t inp_gen_t; /* @@ -320,7 +321,7 @@ struct inpcb { CK_LIST_ENTRY(inpcb) inp_portlist; /* (i/h) */ struct inpcbport *inp_phd; /* (i/h) head of this list */ inp_gen_t inp_gencnt; /* (c) generation count */ - struct llentry *inp_lle; /* cached L2 information */ + void *spare_ptr; /* Spare pointer. */ rt_gen_t inp_rt_cookie; /* generation for route entry */ union { /* cached L3 information */ struct route inp_route; @@ -566,7 +567,8 @@ struct inpcbgroup { * is dynamically resized as processes bind/unbind to that specific group. */ struct inpcblbgroup { - LIST_ENTRY(inpcblbgroup) il_list; + CK_LIST_ENTRY(inpcblbgroup) il_list; + struct epoch_context il_epoch_ctx; uint16_t il_lport; /* (c) */ u_char il_vflag; /* (c) */ u_char il_pad; @@ -578,7 +580,6 @@ struct inpcblbgroup { uint32_t il_inpcnt; /* cur count in il_inp[] (h) */ struct inpcb *il_inp[]; /* (h) */ }; -LIST_HEAD(inpcblbgrouphead, inpcblbgroup); #define INP_LOCK_INIT(inp, d, t) \ rw_init_flags(&(inp)->inp_lock, (t), RW_RECURSE | RW_DUPOK) @@ -744,8 +745,8 @@ int inp_so_options(const struct inpcb *inp); /* * Flags for inp_flags2. */ -#define INP_LLE_VALID 0x00000001 /* cached lle is valid */ -#define INP_RT_VALID 0x00000002 /* cached rtentry is valid */ +#define INP_2UNUSED1 0x00000001 +#define INP_2UNUSED2 0x00000002 #define INP_PCBGROUPWILD 0x00000004 /* in pcbgroup wildcard list */ #define INP_REUSEPORT 0x00000008 /* SO_REUSEPORT option is set */ #define INP_FREED 0x00000010 /* inp itself is not valid */ diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 47351bacb5b6..643a75e2294b 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -153,7 +153,7 @@ ip_tryforward(struct mbuf *m) struct mbuf *m0 = NULL; struct nhop4_basic nh; struct sockaddr_in dst; - struct in_addr odest, dest; + struct in_addr dest, odest, rtdest; uint16_t ip_len, ip_off; int error = 0; struct m_tag *fwd_tag = NULL; @@ -294,12 +294,31 @@ passin: #endif /* + * Next hop forced by pfil(9) hook? + */ + if ((m->m_flags & M_IP_NEXTHOP) && + ((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) { + /* + * Now we will find route to forced destination. + */ + dest.s_addr = ((struct sockaddr_in *) + (fwd_tag + 1))->sin_addr.s_addr; + m_tag_delete(m, fwd_tag); + m->m_flags &= ~M_IP_NEXTHOP; + } + + /* * Find route to destination. */ if (ip_findroute(&nh, dest, m) != 0) return (NULL); /* icmp unreach already sent */ /* + * Avoid second route lookup by caching destination. + */ + rtdest.s_addr = dest.s_addr; + + /* * Step 5: outgoing firewall packet processing */ if (!PFIL_HOOKED(&V_inet_pfil_hook)) @@ -321,6 +340,8 @@ passin: */ if (m->m_flags & M_IP_NEXTHOP) fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); + else + fwd_tag = NULL; if (odest.s_addr != dest.s_addr || fwd_tag != NULL) { /* * Is it now for a local address on this host? @@ -342,7 +363,8 @@ forwardlocal: m_tag_delete(m, fwd_tag); m->m_flags &= ~M_IP_NEXTHOP; } - if (ip_findroute(&nh, dest, m) != 0) + if (dest.s_addr != rtdest.s_addr && + ip_findroute(&nh, dest, m) != 0) return (NULL); /* icmp unreach already sent */ } diff --git a/sys/netinet/tcp_hpts.c b/sys/netinet/tcp_hpts.c index 7c4ad009d73d..32047180f883 100644 --- a/sys/netinet/tcp_hpts.c +++ b/sys/netinet/tcp_hpts.c @@ -167,6 +167,8 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_TCPHPTS, "tcp_hpts", "TCP hpts"); #ifdef RSS +#include <net/netisr.h> +#include <net/rss_config.h> static int tcp_bind_threads = 1; #else static int tcp_bind_threads = 0; @@ -1076,7 +1078,7 @@ hpts_random_cpu(struct inpcb *inp){ static uint16_t hpts_cpuid(struct inpcb *inp){ - uint16_t cpuid; + u_int cpuid; /* diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c index 0f30801540a6..bbdbf448f7cb 100644 --- a/sys/netinet6/frag6.c +++ b/sys/netinet6/frag6.c @@ -218,7 +218,9 @@ frag6_input(struct mbuf **mp, int *offp, int proto) int offset = *offp, nxt, i, next; int first_frag = 0; int fragoff, frgpartlen; /* must be larger than u_int16_t */ - uint32_t hash, hashkey[sizeof(struct in6_addr) * 2 + 1], *hashkeyp; + uint32_t hashkey[(sizeof(struct in6_addr) * 2 + + sizeof(ip6f->ip6f_ident)) / sizeof(uint32_t)]; + uint32_t hash, *hashkeyp; struct ifnet *dstifp; u_int8_t ecn, ecn0; #ifdef RSS diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index b45d04bf1be5..a9c73798b18c 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -846,16 +846,10 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp) * (by a redirect), time to try a default gateway again. */ void -in6_losing(struct inpcb *in6p) +in6_losing(struct inpcb *inp) { - if (in6p->inp_route6.ro_rt) { - RTFREE(in6p->inp_route6.ro_rt); - in6p->inp_route6.ro_rt = (struct rtentry *)NULL; - } - if (in6p->inp_route.ro_lle) - LLE_FREE(in6p->inp_route.ro_lle); /* zeros ro_lle */ - return; + RO_INVALIDATE_CACHE(&inp->inp_route6); } /* @@ -863,15 +857,10 @@ in6_losing(struct inpcb *in6p) * and allocate a (hopefully) better one. */ struct inpcb * -in6_rtchange(struct inpcb *inp, int errno) +in6_rtchange(struct inpcb *inp, int errno __unused) { - if (inp->inp_route6.ro_rt) { - RTFREE(inp->inp_route6.ro_rt); - inp->inp_route6.ro_rt = (struct rtentry *)NULL; - } - if (inp->inp_route.ro_lle) - LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */ + RO_INVALIDATE_CACHE(&inp->inp_route6); return inp; } @@ -900,7 +889,7 @@ in6_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, * - Load balanced group does not contain jailed sockets. * - Load balanced does not contain IPv4 mapped INET6 wild sockets. */ - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { #ifdef INET if (!(grp->il_vflag & INP_IPV6)) continue; diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 7ce29e2e1d83..9c24daf2f7a7 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -804,22 +804,16 @@ again: error = netisr_queue(NETISR_IPV6, m); goto done; } else { - RO_RTFREE(ro); + RO_INVALIDATE_CACHE(ro); needfiblookup = 1; /* Redo the routing table lookup. */ - if (ro->ro_lle) - LLE_FREE(ro->ro_lle); /* zeros ro_lle */ - ro->ro_lle = NULL; } } /* See if fib was changed by packet filter. */ if (fibnum != M_GETFIB(m)) { m->m_flags |= M_SKIP_FIREWALL; fibnum = M_GETFIB(m); - RO_RTFREE(ro); + RO_INVALIDATE_CACHE(ro); needfiblookup = 1; - if (ro->ro_lle) - LLE_FREE(ro->ro_lle); /* zeros ro_lle */ - ro->ro_lle = NULL; } if (needfiblookup) goto again; diff --git a/sys/ofed/drivers/infiniband/core/ib_cm.c b/sys/ofed/drivers/infiniband/core/ib_cm.c index d7fc30fec7d3..b903eeab4a3c 100644 --- a/sys/ofed/drivers/infiniband/core/ib_cm.c +++ b/sys/ofed/drivers/infiniband/core/ib_cm.c @@ -1453,6 +1453,7 @@ static void cm_format_req_event(struct cm_work *work, param->retry_count = cm_req_get_retry_count(req_msg); param->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg); param->srq = cm_req_get_srq(req_msg); + param->ppath_sgid_index = cm_id_priv->av.ah_attr.grh.sgid_index; work->cm_event.private_data = &req_msg->private_data; } @@ -3137,6 +3138,7 @@ out: EXPORT_SYMBOL(ib_send_cm_sidr_req); static void cm_format_sidr_req_event(struct cm_work *work, + const struct cm_id_private *rx_cm_id, struct ib_cm_id *listen_id) { struct cm_sidr_req_msg *sidr_req_msg; @@ -3150,6 +3152,7 @@ static void cm_format_sidr_req_event(struct cm_work *work, param->service_id = sidr_req_msg->service_id; param->bth_pkey = cm_get_bth_pkey(work); param->port = work->port->port_num; + param->sgid_index = rx_cm_id->av.ah_attr.grh.sgid_index; work->cm_event.private_data = &sidr_req_msg->private_data; } @@ -3203,7 +3206,7 @@ static int cm_sidr_req_handler(struct cm_work *work) cm_id_priv->id.service_id = sidr_req_msg->service_id; cm_id_priv->id.service_mask = ~cpu_to_be64(0); - cm_format_sidr_req_event(work, &cur_cm_id_priv->id); + cm_format_sidr_req_event(work, cm_id_priv, &cur_cm_id_priv->id); cm_process_work(cm_id_priv, work); cm_deref_id(cur_cm_id_priv); return 0; diff --git a/sys/ofed/drivers/infiniband/core/ib_cma.c b/sys/ofed/drivers/infiniband/core/ib_cma.c index 42e7b3ad811f..0e20a04b3464 100644 --- a/sys/ofed/drivers/infiniband/core/ib_cma.c +++ b/sys/ofed/drivers/infiniband/core/ib_cma.c @@ -733,6 +733,10 @@ struct rdma_cm_id *rdma_create_id(struct vnet *net, { struct rdma_id_private *id_priv; +#ifdef VIMAGE + if (net == NULL) + return ERR_PTR(-EINVAL); +#endif id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL); if (!id_priv) return ERR_PTR(-ENOMEM); @@ -751,7 +755,7 @@ struct rdma_cm_id *rdma_create_id(struct vnet *net, INIT_LIST_HEAD(&id_priv->listen_list); INIT_LIST_HEAD(&id_priv->mc_list); get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num); - id_priv->id.route.addr.dev_addr.net = TD_TO_VNET(curthread); + id_priv->id.route.addr.dev_addr.net = net; return &id_priv->id; } @@ -1263,10 +1267,10 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev, const struct sockaddr_in *src_addr) { #ifdef INET - struct sockaddr_in dst_tmp = *dst_addr; + struct sockaddr_in src_tmp = *src_addr; __be32 daddr = dst_addr->sin_addr.s_addr, saddr = src_addr->sin_addr.s_addr; - struct net_device *src_dev; + struct net_device *dst_dev; struct rtentry *rte; bool ret; @@ -1276,29 +1280,29 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev, ipv4_is_loopback(saddr)) return false; - src_dev = ip_dev_find(net_dev->if_vnet, saddr); - if (src_dev != net_dev) { - if (src_dev != NULL) - dev_put(src_dev); + dst_dev = ip_dev_find(net_dev->if_vnet, daddr); + if (dst_dev != net_dev) { + if (dst_dev != NULL) + dev_put(dst_dev); return false; } - dev_put(src_dev); + dev_put(dst_dev); /* * Make sure the socket address length field * is set, else rtalloc1() will fail. */ - dst_tmp.sin_len = sizeof(dst_tmp); + src_tmp.sin_len = sizeof(src_tmp); CURVNET_SET(net_dev->if_vnet); - rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0); - CURVNET_RESTORE(); + rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0); if (rte != NULL) { ret = (rte->rt_ifp == net_dev); RTFREE_LOCKED(rte); } else { ret = false; } + CURVNET_RESTORE(); return ret; #else return false; @@ -1310,31 +1314,42 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev, const struct sockaddr_in6 *src_addr) { #ifdef INET6 - struct sockaddr_in6 dst_tmp = *dst_addr; - struct in6_addr in6_addr = src_addr->sin6_addr; - struct net_device *src_dev; + struct sockaddr_in6 src_tmp = *src_addr; + struct in6_addr in6_addr = dst_addr->sin6_addr; + struct net_device *dst_dev; struct rtentry *rte; bool ret; - src_dev = ip6_dev_find(net_dev->if_vnet, in6_addr); - if (src_dev != net_dev) + dst_dev = ip6_dev_find(net_dev->if_vnet, in6_addr); + if (dst_dev != net_dev) { + if (dst_dev != NULL) + dev_put(dst_dev); return false; + } + + CURVNET_SET(net_dev->if_vnet); /* * Make sure the socket address length field * is set, else rtalloc1() will fail. */ - dst_tmp.sin6_len = sizeof(dst_tmp); + src_tmp.sin6_len = sizeof(src_tmp); - CURVNET_SET(net_dev->if_vnet); - rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0); - CURVNET_RESTORE(); + /* + * Make sure the scope ID gets embedded, else rtalloc1() will + * resolve to the loopback interface. + */ + src_tmp.sin6_scope_id = net_dev->if_index; + sa6_embedscope(&src_tmp, 0); + + rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0); if (rte != NULL) { ret = (rte->rt_ifp == net_dev); RTFREE_LOCKED(rte); } else { ret = false; } + CURVNET_RESTORE(); return ret; #else return false; @@ -1364,6 +1379,26 @@ static bool validate_net_dev(struct net_device *net_dev, } } +static struct net_device * +roce_get_net_dev_by_cm_event(struct ib_device *device, u8 port_num, + const struct ib_cm_event *ib_event) +{ + struct ib_gid_attr sgid_attr; + union ib_gid sgid; + int err = -EINVAL; + + if (ib_event->event == IB_CM_REQ_RECEIVED) { + err = ib_get_cached_gid(device, port_num, + ib_event->param.req_rcvd.ppath_sgid_index, &sgid, &sgid_attr); + } else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) { + err = ib_get_cached_gid(device, port_num, + ib_event->param.sidr_req_rcvd.sgid_index, &sgid, &sgid_attr); + } + if (err) + return (NULL); + return (sgid_attr.ndev); +} + static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event, const struct cma_req_info *req) { @@ -1379,8 +1414,14 @@ static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event, if (err) return ERR_PTR(err); - net_dev = ib_get_net_dev_by_params(req->device, req->port, req->pkey, - gid, listen_addr); + if (rdma_protocol_roce(req->device, req->port)) { + net_dev = roce_get_net_dev_by_cm_event(req->device, req->port, + ib_event); + } else { + net_dev = ib_get_net_dev_by_params(req->device, req->port, + req->pkey, + gid, listen_addr); + } if (!net_dev) return ERR_PTR(-ENODEV); @@ -1516,10 +1557,6 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id, if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) { /* Assuming the protocol is AF_IB */ *net_dev = NULL; - } else if (cma_protocol_roce_dev_port(req.device, req.port)) { - /* TODO find the net dev matching the request parameters - * through the RoCE GID table */ - *net_dev = NULL; } else { return ERR_CAST(*net_dev); } diff --git a/sys/ofed/drivers/infiniband/core/ib_roce_gid_mgmt.c b/sys/ofed/drivers/infiniband/core/ib_roce_gid_mgmt.c index 5a65207a82f3..1dae52bac08a 100644 --- a/sys/ofed/drivers/infiniband/core/ib_roce_gid_mgmt.c +++ b/sys/ofed/drivers/infiniband/core/ib_roce_gid_mgmt.c @@ -149,16 +149,6 @@ roce_gid_enum_netdev_default(struct ib_device *ib_dev, return (hweight_long(gid_type_mask)); } -#define ETH_IPOIB_DRV_NAME "ib" - -static inline int -is_eth_ipoib_intf(struct net_device *dev) -{ - if (strcmp(dev->if_dname, ETH_IPOIB_DRV_NAME)) - return 0; - return 1; -} - static void roce_gid_update_addr_callback(struct ib_device *device, u8 port, struct net_device *ndev, void *cookie) @@ -322,15 +312,15 @@ roce_gid_queue_scan_event(struct net_device *ndev) struct roce_netdev_event_work *work; retry: - if (is_eth_ipoib_intf(ndev)) - return; - - if (ndev->if_type != IFT_ETHER) { - if (ndev->if_type == IFT_L2VLAN) { - ndev = rdma_vlan_dev_real_dev(ndev); - if (ndev != NULL) - goto retry; - } + switch (ndev->if_type) { + case IFT_ETHER: + break; + case IFT_L2VLAN: + ndev = rdma_vlan_dev_real_dev(ndev); + if (ndev != NULL) + goto retry; + /* FALLTHROUGH */ + default: return; } diff --git a/sys/ofed/drivers/infiniband/core/ib_uverbs_marshall.c b/sys/ofed/drivers/infiniband/core/ib_uverbs_marshall.c index 11df70fff697..bf23f264d903 100644 --- a/sys/ofed/drivers/infiniband/core/ib_uverbs_marshall.c +++ b/sys/ofed/drivers/infiniband/core/ib_uverbs_marshall.c @@ -146,7 +146,7 @@ void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, dst->packet_life_time_selector = src->packet_life_time_selector; memset(dst->dmac, 0, sizeof(dst->dmac)); - dst->net = NULL; + dst->net = TD_TO_VNET(curthread); dst->ifindex = 0; dst->gid_type = IB_GID_TYPE_IB; } diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c index aee91c29eb0a..6a8995a98d09 100644 --- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -54,6 +54,8 @@ static int ipoib_resolvemulti(struct ifnet *, struct sockaddr **, #include <net/ip.h> #include <net/ipv6.h> +#include <rdma/ib_cache.h> + MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); MODULE_LICENSE("Dual BSD/GPL"); @@ -90,6 +92,10 @@ struct ib_sa_client ipoib_sa_client; static void ipoib_add_one(struct ib_device *device); static void ipoib_remove_one(struct ib_device *device, void *client_data); +static struct net_device *ipoib_get_net_dev_by_params( + struct ib_device *dev, u8 port, u16 pkey, + const union ib_gid *gid, const struct sockaddr *addr, + void *client_data); static void ipoib_start(struct ifnet *dev); static int ipoib_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro); @@ -163,7 +169,8 @@ ipoib_mtap_proto(struct ifnet *ifp, struct mbuf *mb, uint16_t proto) static struct ib_client ipoib_client = { .name = "ipoib", .add = ipoib_add_one, - .remove = ipoib_remove_one + .remove = ipoib_remove_one, + .get_net_dev_by_params = ipoib_get_net_dev_by_params, }; int @@ -1113,6 +1120,156 @@ ipoib_remove_one(struct ib_device *device, void *client_data) kfree(dev_list); } +static int +ipoib_match_dev_addr(const struct sockaddr *addr, struct net_device *dev) +{ + struct ifaddr *ifa; + int retval = 0; + + CURVNET_SET(dev->if_vnet); + IF_ADDR_RLOCK(dev); + CK_STAILQ_FOREACH(ifa, &dev->if_addrhead, ifa_link) { + if (ifa->ifa_addr == NULL || + ifa->ifa_addr->sa_family != addr->sa_family || + ifa->ifa_addr->sa_len != addr->sa_len) { + continue; + } + if (memcmp(ifa->ifa_addr, addr, addr->sa_len) == 0) { + retval = 1; + break; + } + } + IF_ADDR_RUNLOCK(dev); + CURVNET_RESTORE(); + + return (retval); +} + +/* + * ipoib_match_gid_pkey_addr - returns the number of IPoIB netdevs on + * top a given ipoib device matching a pkey_index and address, if one + * exists. + * + * @found_net_dev: contains a matching net_device if the return value + * >= 1, with a reference held. + */ +static int +ipoib_match_gid_pkey_addr(struct ipoib_dev_priv *priv, + const union ib_gid *gid, u16 pkey_index, const struct sockaddr *addr, + struct net_device **found_net_dev) +{ + struct ipoib_dev_priv *child_priv; + int matches = 0; + + if (priv->pkey_index == pkey_index && + (!gid || !memcmp(gid, &priv->local_gid, sizeof(*gid)))) { + if (addr == NULL || ipoib_match_dev_addr(addr, priv->dev) != 0) { + if (*found_net_dev == NULL) { + struct net_device *net_dev; + + if (priv->parent != NULL) + net_dev = priv->parent; + else + net_dev = priv->dev; + *found_net_dev = net_dev; + dev_hold(net_dev); + } + matches++; + } + } + + /* Check child interfaces */ + mutex_lock(&priv->vlan_mutex); + list_for_each_entry(child_priv, &priv->child_intfs, list) { + matches += ipoib_match_gid_pkey_addr(child_priv, gid, + pkey_index, addr, found_net_dev); + if (matches > 1) + break; + } + mutex_unlock(&priv->vlan_mutex); + + return matches; +} + +/* + * __ipoib_get_net_dev_by_params - returns the number of matching + * net_devs found (between 0 and 2). Also return the matching + * net_device in the @net_dev parameter, holding a reference to the + * net_device, if the number of matches >= 1 + */ +static int +__ipoib_get_net_dev_by_params(struct list_head *dev_list, u8 port, + u16 pkey_index, const union ib_gid *gid, + const struct sockaddr *addr, struct net_device **net_dev) +{ + struct ipoib_dev_priv *priv; + int matches = 0; + + *net_dev = NULL; + + list_for_each_entry(priv, dev_list, list) { + if (priv->port != port) + continue; + + matches += ipoib_match_gid_pkey_addr(priv, gid, pkey_index, + addr, net_dev); + + if (matches > 1) + break; + } + + return matches; +} + +static struct net_device * +ipoib_get_net_dev_by_params(struct ib_device *dev, u8 port, u16 pkey, + const union ib_gid *gid, const struct sockaddr *addr, void *client_data) +{ + struct net_device *net_dev; + struct list_head *dev_list = client_data; + u16 pkey_index; + int matches; + int ret; + + if (!rdma_protocol_ib(dev, port)) + return NULL; + + ret = ib_find_cached_pkey(dev, port, pkey, &pkey_index); + if (ret) + return NULL; + + if (!dev_list) + return NULL; + + /* See if we can find a unique device matching the L2 parameters */ + matches = __ipoib_get_net_dev_by_params(dev_list, port, pkey_index, + gid, NULL, &net_dev); + + switch (matches) { + case 0: + return NULL; + case 1: + return net_dev; + } + + dev_put(net_dev); + + /* Couldn't find a unique device with L2 parameters only. Use L3 + * address to uniquely match the net device */ + matches = __ipoib_get_net_dev_by_params(dev_list, port, pkey_index, + gid, addr, &net_dev); + switch (matches) { + case 0: + return NULL; + default: + dev_warn_ratelimited(&dev->dev, + "duplicate IP address detected\n"); + /* Fall through */ + case 1: + return net_dev; + } +} + static void ipoib_config_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) { diff --git a/sys/ofed/include/rdma/ib_addr.h b/sys/ofed/include/rdma/ib_addr.h index ab95e9e036d9..49caf7a7844d 100644 --- a/sys/ofed/include/rdma/ib_addr.h +++ b/sys/ofed/include/rdma/ib_addr.h @@ -167,7 +167,7 @@ static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev) { uint16_t tag; - if (dev->if_pcp != IFNET_PCP_NONE) + if (dev->if_type == IFT_ETHER && dev->if_pcp != IFNET_PCP_NONE) return 0x0000; /* prio-tagged traffic */ if (VLAN_TAG(__DECONST(struct ifnet *, dev), &tag) != 0) return 0xffff; @@ -221,7 +221,11 @@ static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr, struct net_device *dev; struct ifaddr *ifa; - dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); +#ifdef VIMAGE + if (dev_addr->net == NULL) + return; +#endif + dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if); if (dev) { CK_STAILQ_FOREACH(ifa, &dev->if_addrhead, ifa_link) { if (ifa->ifa_addr == NULL || @@ -350,7 +354,7 @@ static inline u16 rdma_get_vlan_id(union ib_gid *dgid) static inline struct net_device *rdma_vlan_dev_real_dev(struct net_device *dev) { - if (dev->if_pcp != IFNET_PCP_NONE) + if (dev->if_type == IFT_ETHER && dev->if_pcp != IFNET_PCP_NONE) return dev; /* prio-tagged traffic */ return VLAN_TRUNKDEV(__DECONST(struct ifnet *, dev)); } diff --git a/sys/ofed/include/rdma/ib_cm.h b/sys/ofed/include/rdma/ib_cm.h index 48309328d62a..8806494766f6 100644 --- a/sys/ofed/include/rdma/ib_cm.h +++ b/sys/ofed/include/rdma/ib_cm.h @@ -125,6 +125,13 @@ struct ib_cm_req_event_param { struct ib_sa_path_rec *primary_path; struct ib_sa_path_rec *alternate_path; + /* + * SGID index of the primary path. Currently only + * useful for RoCE. Alternate path GID attributes + * are not yet supported. + */ + u8 ppath_sgid_index; + __be64 remote_ca_guid; u32 remote_qkey; u32 remote_qpn; @@ -231,6 +238,13 @@ struct ib_cm_apr_event_param { struct ib_cm_sidr_req_event_param { struct ib_cm_id *listen_id; __be64 service_id; + + /* + * SGID index of the request. Currently only + * useful for RoCE. + */ + u8 sgid_index; + /* P_Key that was used by the GMP's BTH header */ u16 bth_pkey; u8 port; diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h index 7bed3548ee7c..451b730225ca 100644 --- a/sys/powerpc/include/pcb.h +++ b/sys/powerpc/include/pcb.h @@ -56,6 +56,7 @@ struct pcb { #define PCB_VEC 0x4 /* Process had Altivec initialized */ #define PCB_VSX 0x8 /* Process had VSX initialized */ #define PCB_CDSCR 0x10 /* Process had Custom DSCR initialized */ +#define PCB_HTM 0x20 /* Process had HTM initialized */ struct fpu { union { double fpr; @@ -73,6 +74,11 @@ struct pcb { } pcb_vec __aligned(16); /* Vector processor */ unsigned int pcb_veccpu; /* which CPU had our vector stuff. */ + struct htm { + uint64_t tfhar; + uint64_t texasr; + uint64_t tfiar; + } pcb_htm; union { struct { diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h index 5e5a24f7563b..48bc4a3f6d7a 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -45,6 +45,7 @@ struct pvo_entry; struct pmap *pc_curpmap; /* current pmap */ \ struct thread *pc_fputhread; /* current fpu user */ \ struct thread *pc_vecthread; /* current vec user */ \ + struct thread *pc_htmthread; /* current htm user */ \ uintptr_t pc_hwref; \ int pc_bsp; \ volatile int pc_awake; \ diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC index 0405b1921cd7..2975ecbec413 100644 --- a/sys/riscv/conf/GENERIC +++ b/sys/riscv/conf/GENERIC @@ -88,6 +88,15 @@ device vtnet # VirtIO Ethernet device device virtio_blk # VirtIO Block device device virtio_mmio # VirtIO MMIO bus +# DTrace support +# device dtrace +# device dtrace_profile +# device dtrace_sdt +# device dtrace_fbt +# device dtrace_systrace +# device dtrace_prototype +# device dtraceall + # Serial (COM) ports device uart # Generic UART driver device uart_ns8250 # ns8250-type UART driver diff --git a/sys/riscv/include/asm.h b/sys/riscv/include/asm.h index 5b517322732c..87736980cdc0 100644 --- a/sys/riscv/include/asm.h +++ b/sys/riscv/include/asm.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -63,4 +63,12 @@ ld tmp, TD_PCB(tmp); /* Load the pcb */ \ sd handler, PCB_ONFAULT(tmp) /* Set the handler */ +#define ENTER_USER_ACCESS(tmp) \ + li tmp, SSTATUS_SUM; \ + csrs sstatus, tmp + +#define EXIT_USER_ACCESS(tmp) \ + li tmp, SSTATUS_SUM; \ + csrc sstatus, tmp + #endif /* _MACHINE_ASM_H_ */ diff --git a/sys/riscv/include/riscv_opcode.h b/sys/riscv/include/riscv_opcode.h deleted file mode 100644 index b346588f01df..000000000000 --- a/sys/riscv/include/riscv_opcode.h +++ /dev/null @@ -1,116 +0,0 @@ -/*- - * Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com> - * All rights reserved. - * - * Portions of this software were developed by SRI International and the - * University of Cambridge Computer Laboratory under DARPA/AFRL contract - * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. - * - * Portions of this software were developed by the University of Cambridge - * Computer Laboratory as part of the CTSRD Project, with support from the - * UK Higher Education Innovation Fund (HEIF). - * - * 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. - * - * $FreeBSD$ - */ - -#ifndef _MACHINE_RISCV_OPCODE_H_ -#define _MACHINE_RISCV_OPCODE_H_ - -/* - * Define the instruction formats and opcode values for the - * RISC-V instruction set. - */ -#include <machine/endian.h> - -/* - * Define the instruction formats. - */ -typedef union { - unsigned word; - - struct { - unsigned opcode: 7; - unsigned rd: 5; - unsigned funct3: 3; - unsigned rs1: 5; - unsigned rs2: 5; - unsigned funct7: 7; - } RType; - - struct { - unsigned opcode: 7; - unsigned rd: 5; - unsigned funct3: 3; - unsigned rs1: 5; - unsigned rs2: 6; - unsigned funct7: 6; - } R2Type; - - struct { - unsigned opcode: 7; - unsigned rd: 5; - unsigned funct3: 3; - unsigned rs1: 5; - unsigned imm: 12; - } IType; - - struct { - unsigned opcode: 7; - unsigned imm0_4: 5; - unsigned funct3: 3; - unsigned rs1: 5; - unsigned rs2: 5; - unsigned imm5_11: 7; - } SType; - - struct { - unsigned opcode: 7; - unsigned imm11: 1; - unsigned imm1_4: 4; - unsigned funct3: 3; - unsigned rs1: 5; - unsigned rs2: 5; - unsigned imm5_10: 6; - unsigned imm12: 1; - } SBType; - - struct { - unsigned opcode: 7; - unsigned rd: 5; - unsigned imm12_31: 20; - } UType; - - struct { - unsigned opcode: 7; - unsigned rd: 5; - unsigned imm12_19: 8; - unsigned imm11: 1; - unsigned imm1_10: 10; - unsigned imm20: 1; - } UJType; -} InstFmt; - -#define RISCV_OPCODE(r) (r & 0x7f) - -#endif /* !_MACHINE_RISCV_OPCODE_H_ */ diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h index 421b6e074437..fae70d9e0441 100644 --- a/sys/riscv/include/riscvreg.h +++ b/sys/riscv/include/riscvreg.h @@ -157,10 +157,31 @@ #define XLEN 8 #define INSN_SIZE 4 +#define INSN_C_SIZE 2 -#define RISCV_INSN_NOP 0x00000013 -#define RISCV_INSN_BREAK 0x00100073 -#define RISCV_INSN_RET 0x00008067 +#define X_RA 1 +#define X_SP 2 +#define X_GP 3 +#define X_TP 4 +#define X_T0 5 +#define X_T1 6 +#define X_T2 7 +#define X_T3 28 + +#define RD_SHIFT 7 +#define RD_MASK (0x1f << RD_SHIFT) +#define RS1_SHIFT 15 +#define RS1_MASK (0x1f << RS1_SHIFT) +#define RS1_SP (X_SP << RS1_SHIFT) +#define RS2_SHIFT 20 +#define RS2_MASK (0x1f << RS2_SHIFT) +#define RS2_RA (X_RA << RS2_SHIFT) +#define IMM_SHIFT 20 +#define IMM_MASK (0xfff << IMM_SHIFT) + +#define RS2_C_SHIFT 2 +#define RS2_C_MASK (0x1f << RS2_C_SHIFT) +#define RS2_C_RA (X_RA << RS2_C_SHIFT) #define CSR_ZIMM(val) \ (__builtin_constant_p(val) && ((u_long)(val) < 32)) diff --git a/sys/riscv/riscv/copyinout.S b/sys/riscv/riscv/copyinout.S index a36f7ce63593..5e80f4900c8b 100644 --- a/sys/riscv/riscv/copyinout.S +++ b/sys/riscv/riscv/copyinout.S @@ -35,6 +35,7 @@ #include <machine/asm.h> __FBSDID("$FreeBSD$"); +#include <machine/riscvreg.h> #include <sys/errno.h> #include "assym.inc" @@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$"); */ ENTRY(copyio_fault) SET_FAULT_HANDLER(x0, a1) /* Clear the handler */ + EXIT_USER_ACCESS(a1) copyio_fault_nopcb: li a0, EFAULT ret @@ -62,6 +64,7 @@ ENTRY(copyout) la a6, copyio_fault /* Get the handler address */ SET_FAULT_HANDLER(a6, a7) /* Set the handler */ + ENTER_USER_ACCESS(a7) 1: lb a4, 0(a0) /* Load from kaddr */ addi a0, a0, 1 @@ -70,6 +73,7 @@ ENTRY(copyout) addi a2, a2, -1 /* len-- */ bnez a2, 1b + EXIT_USER_ACCESS(a7) SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ 2: li a0, 0 /* return 0 */ @@ -89,6 +93,7 @@ ENTRY(copyin) la a6, copyio_fault /* Get the handler address */ SET_FAULT_HANDLER(a6, a7) /* Set the handler */ + ENTER_USER_ACCESS(a7) 1: lb a4, 0(a0) /* Load from uaddr */ addi a0, a0, 1 @@ -97,6 +102,7 @@ ENTRY(copyin) addi a2, a2, -1 /* len-- */ bnez a2, 1b + EXIT_USER_ACCESS(a7) SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ 2: li a0, 0 /* return 0 */ @@ -111,12 +117,13 @@ END(copyin) ENTRY(copyinstr) mv a5, x0 /* count = 0 */ beqz a2, 3f /* If len == 0 then skip loop */ - li a7, VM_MAXUSER_ADDRESS la a6, copyio_fault /* Get the handler address */ SET_FAULT_HANDLER(a6, a7) /* Set the handler */ + ENTER_USER_ACCESS(a7) -1: bgt a7, a0, copyio_fault + li a7, VM_MAXUSER_ADDRESS +1: bgt a0, a7, copyio_fault lb a4, 0(a0) /* Load from uaddr */ addi a0, a0, 1 sb a4, 0(a1) /* Store in kaddr */ @@ -125,8 +132,9 @@ ENTRY(copyinstr) addi a2, a2, -1 /* len-- */ addi a5, a5, 1 /* count++ */ bnez a2, 1b - -2: SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ + +2: EXIT_USER_ACCESS(a7) + SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ 3: beqz a3, 4f /* Check if done != NULL */ addi a5, a5, 1 /* count++ */ diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S index ef38fa1c108e..3904a67efae1 100644 --- a/sys/riscv/riscv/exception.S +++ b/sys/riscv/riscv/exception.S @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -116,11 +116,8 @@ __FBSDID("$FreeBSD$"); .macro load_registers el ld t0, (TF_SSTATUS)(sp) .if \el == 0 - /* - * Ensure user interrupts will be enabled on eret - * and supervisor mode can access userspace on trap. - */ - li t1, (SSTATUS_SPIE | SSTATUS_SUM) + /* Ensure user interrupts will be enabled on eret */ + li t1, SSTATUS_SPIE or t0, t0, t1 .else /* diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S index 4b2e6ad6eed0..e8ba3ceefe96 100644 --- a/sys/riscv/riscv/locore.S +++ b/sys/riscv/riscv/locore.S @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -62,9 +62,6 @@ _start: mv s10, a0 /* s10 = hart id */ mv s11, a1 /* s11 = dtbp */ - li t0, SSTATUS_SUM - csrs sstatus, t0 - /* Direct secondary cores to mpentry */ bnez s10, mpentry diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 840f0bf3c0a9..64d20126f3ad 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -734,12 +734,14 @@ cache_setup(void) vm_offset_t fake_preload_metadata(struct riscv_bootparams *rvbp __unused) { + static uint32_t fake_preload[35]; #ifdef DDB vm_offset_t zstart = 0, zend = 0; #endif vm_offset_t lastaddr; - int i = 0; - static uint32_t fake_preload[35]; + int i; + + i = 0; fake_preload[i++] = MODINFO_NAME; fake_preload[i++] = strlen("kernel") + 1; @@ -751,12 +753,13 @@ fake_preload_metadata(struct riscv_bootparams *rvbp __unused) i += 3; fake_preload[i++] = MODINFO_ADDR; fake_preload[i++] = sizeof(vm_offset_t); - fake_preload[i++] = (uint64_t)(KERNBASE + KERNENTRY); + *(vm_offset_t *)&fake_preload[i++] = + (vm_offset_t)(KERNBASE + KERNENTRY); i += 1; fake_preload[i++] = MODINFO_SIZE; - fake_preload[i++] = sizeof(uint64_t); - printf("end is 0x%016lx\n", (uint64_t)&end); - fake_preload[i++] = (uint64_t)&end - (uint64_t)(KERNBASE + KERNENTRY); + fake_preload[i++] = sizeof(vm_offset_t); + fake_preload[i++] = (vm_offset_t)&end - + (vm_offset_t)(KERNBASE + KERNENTRY); i += 1; #ifdef DDB #if 0 diff --git a/sys/riscv/riscv/support.S b/sys/riscv/riscv/support.S index e3848cd94c9a..e59302bea9aa 100644 --- a/sys/riscv/riscv/support.S +++ b/sys/riscv/riscv/support.S @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <machine/setjmp.h> +#include <machine/riscvreg.h> #include "assym.inc" @@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$"); */ ENTRY(fsu_fault) SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */ + EXIT_USER_ACCESS(a1) fsu_fault_nopcb: li a0, -1 ret @@ -57,11 +59,13 @@ ENTRY(casueword32) bgt a0, a4, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a4) /* And set it */ + ENTER_USER_ACCESS(a4) 1: lr.w a4, 0(a0) /* Load-exclusive the data */ bne a4, a1, 2f /* If not equal then exit */ sc.w a5, a3, 0(a0) /* Store the new data */ bnez a5, 1b /* Retry on failure */ -2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */ +2: EXIT_USER_ACCESS(a5) + SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */ sw a4, 0(a2) /* Store the read data */ li a0, 0 /* Success */ ret /* Return */ @@ -75,11 +79,13 @@ ENTRY(casueword) bgt a0, a4, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a4) /* And set it */ + ENTER_USER_ACCESS(a4) 1: lr.d a4, 0(a0) /* Load-exclusive the data */ bne a4, a1, 2f /* If not equal then exit */ sc.d a5, a3, 0(a0) /* Store the new data */ bnez a5, 1b /* Retry on failure */ -2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */ +2: EXIT_USER_ACCESS(a5) + SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */ sd a4, 0(a2) /* Store the read data */ li a0, 0 /* Success */ ret /* Return */ @@ -93,7 +99,9 @@ ENTRY(fubyte) bgt a0, a1, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a1) /* And set it */ + ENTER_USER_ACCESS(a1) lb a0, 0(a0) /* Try loading the data */ + EXIT_USER_ACCESS(a1) SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */ ret /* Return */ END(fubyte) @@ -106,7 +114,9 @@ ENTRY(fuword16) bgt a0, a1, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a1) /* And set it */ + ENTER_USER_ACCESS(a1) lh a0, 0(a0) /* Try loading the data */ + EXIT_USER_ACCESS(a1) SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */ ret /* Return */ END(fuword16) @@ -119,7 +129,9 @@ ENTRY(fueword32) bgt a0, a2, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a2) /* And set it */ + ENTER_USER_ACCESS(a2) lw a0, 0(a0) /* Try loading the data */ + EXIT_USER_ACCESS(a2) SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ sw a0, 0(a1) /* Save the data in kernel space */ li a0, 0 /* Success */ @@ -136,7 +148,9 @@ EENTRY(fueword64) bgt a0, a2, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a2) /* And set it */ + ENTER_USER_ACCESS(a2) ld a0, 0(a0) /* Try loading the data */ + EXIT_USER_ACCESS(a2) SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ sd a0, 0(a1) /* Save the data in kernel space */ li a0, 0 /* Success */ @@ -152,7 +166,9 @@ ENTRY(subyte) bgt a0, a2, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a2) /* And set it */ + ENTER_USER_ACCESS(a2) sb a1, 0(a0) /* Try storing the data */ + EXIT_USER_ACCESS(a2) SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ li a0, 0 /* Success */ ret /* Return */ @@ -166,7 +182,9 @@ ENTRY(suword16) bgt a0, a2, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a2) /* And set it */ + ENTER_USER_ACCESS(a2) sh a1, 0(a0) /* Try storing the data */ + EXIT_USER_ACCESS(a2) SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ li a0, 0 /* Success */ ret /* Return */ @@ -180,7 +198,9 @@ ENTRY(suword32) bgt a0, a2, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a2) /* And set it */ + ENTER_USER_ACCESS(a2) sw a1, 0(a0) /* Try storing the data */ + EXIT_USER_ACCESS(a2) SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ li a0, 0 /* Success */ ret /* Return */ @@ -195,7 +215,9 @@ EENTRY(suword64) bgt a0, a2, fsu_fault_nopcb la a6, fsu_fault /* Load the fault handler */ SET_FAULT_HANDLER(a6, a2) /* And set it */ + ENTER_USER_ACCESS(a2) sd a1, 0(a0) /* Try storing the data */ + EXIT_USER_ACCESS(a2) SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ li a0, 0 /* Success */ ret /* Return */ diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c index 9ba560d43a49..14bb0ee3430f 100644 --- a/sys/riscv/riscv/vm_machdep.c +++ b/sys/riscv/riscv/vm_machdep.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -105,7 +105,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) tf->tf_a[0] = 0; tf->tf_a[1] = 0; tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */ - tf->tf_sstatus |= (SSTATUS_SUM); /* Supervisor can access userspace. */ tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */ td2->td_frame = tf; diff --git a/sys/security/audit/audit_bsm_db.c b/sys/security/audit/audit_bsm_db.c index 36d79c960d0d..41a525a12ea1 100644 --- a/sys/security/audit/audit_bsm_db.c +++ b/sys/security/audit/audit_bsm_db.c @@ -1,6 +1,6 @@ /* * Copyright (c) 1999-2009 Apple Inc. - * Copyright (c) 2005, 2016-2017 Robert N. M. Watson + * Copyright (c) 2005, 2016-2018 Robert N. M. Watson * All rights reserved. * * Portions of this software were developed by BAE Systems, the University of @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <sys/filedesc.h> #include <sys/libkern.h> +#include <sys/linker.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/proc.h> @@ -91,6 +92,7 @@ static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; * struct evname_elem is defined in audit_private.h so that audit_dtrace.c can * use the definition. */ +#define EVNAMEMAP_HASH_TABLE_MODULE "etc_security_audit_event" #define EVNAMEMAP_HASH_TABLE_SIZE 251 struct evname_list { LIST_HEAD(, evname_elem) enl_head; @@ -261,6 +263,85 @@ au_evnamemap_insert(au_event_t event, const char *name) EVNAMEMAP_WUNLOCK(); } +/* + * If /etc/security/audit_event has been preloaded by the boot loader, parse + * it to build an initial set of event number<->name mappings. + */ +static void +au_evnamemap_init_preload(void) +{ + caddr_t kmdp; + char *endptr, *line, *nextline, *ptr; + const char *evnum_str, *evname; + size_t size; + long evnum; + u_int lineno; + + kmdp = preload_search_by_type(EVNAMEMAP_HASH_TABLE_MODULE); + if (kmdp == NULL) + return; + ptr = preload_fetch_addr(kmdp); + size = preload_fetch_size(kmdp); + + /* + * Parse preloaded configuration file "in place". Assume that the + * last character is a new line, meaning that we can replace it with a + * nul byte safely. We can then use strsep(3) to process the full + * buffer. + */ + ptr[size - 1] = '\0'; + + /* + * Process line by line. + */ + nextline = ptr; + lineno = 0; + while ((line = strsep(&nextline, "\n")) != NULL) { + /* + * Skip any leading white space. + */ + while (line[0] == ' ' || line[0] == '\t') + line++; + + /* + * Skip blank lines and comment lines. + */ + if (line[0] == '\0' || line[0] == '#') { + lineno++; + continue; + } + + /* + * Parse each line -- ":"-separated tuple of event number, + * event name, and other material we are less interested in. + */ + evnum_str = strsep(&line, ":"); + if (evnum_str == NULL || *evnum_str == '\0') { + printf("%s: Invalid line %u - evnum strsep\n", + __func__, lineno); + lineno++; + continue; + } + evnum = strtol(evnum_str, &endptr, 10); + if (*evnum_str == '\0' || *endptr != '\0' || + evnum <= 0 || evnum > UINT16_MAX) { + printf("%s: Invalid line %u - evnum strtol\n", + __func__, lineno); + lineno++; + continue; + } + evname = strsep(&line, ":"); + if (evname == NULL || *evname == '\0') { + printf("%s: Invalid line %u - evname strsp\n", + __func__, lineno); + lineno++; + continue; + } + au_evnamemap_insert(evnum, evname); + lineno++; + } +} + void au_evnamemap_init(void) { @@ -269,13 +350,7 @@ au_evnamemap_init(void) EVNAMEMAP_LOCK_INIT(); for (i = 0; i < EVNAMEMAP_HASH_TABLE_SIZE; i++) LIST_INIT(&evnamemap_hash[i].enl_head); - - /* - * XXXRW: Unlike the event-to-class mapping, we don't attempt to - * pre-populate the list. Perhaps we should...? But not sure we - * really want to duplicate /etc/security/audit_event in the kernel - * -- and we'd need a way to remove names? - */ + au_evnamemap_init_preload(); } /* diff --git a/sys/sys/efi.h b/sys/sys/efi.h index 0a0699d43256..622df48e7f32 100644 --- a/sys/sys/efi.h +++ b/sys/sys/efi.h @@ -169,10 +169,13 @@ struct efi_systbl { extern vm_paddr_t efi_systbl_phys; +struct efirt_callinfo; + /* Internal MD EFI functions */ int efi_arch_enter(void); void efi_arch_leave(void); vm_offset_t efi_phys_to_kva(vm_paddr_t); +int efi_rt_arch_call(struct efirt_callinfo *); bool efi_create_1t1_map(struct efi_md *, int, int); void efi_destroy_1t1_map(void); diff --git a/sys/sys/param.h b/sys/sys/param.h index 91b296c56304..d3a233867658 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -60,7 +60,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1200083 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200084 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 44d3cfab79dd..ab8a925715d0 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -363,15 +363,11 @@ void realitexpire(void *); int sysbeep(int hertz, int period); -void hardclock(int usermode, uintfptr_t pc); -void hardclock_cnt(int cnt, int usermode); -void hardclock_cpu(int usermode); +void hardclock(int cnt, int usermode); void hardclock_sync(int cpu); void softclock(void *); -void statclock(int usermode); -void statclock_cnt(int cnt, int usermode); -void profclock(int usermode, uintfptr_t pc); -void profclock_cnt(int cnt, int usermode, uintfptr_t pc); +void statclock(int cnt, int usermode); +void profclock(int cnt, int usermode, uintfptr_t pc); int hardclockintr(void); diff --git a/sys/sys/vmmeter.h b/sys/sys/vmmeter.h index 3c570b0a6b7f..c41b151fa502 100644 --- a/sys/sys/vmmeter.h +++ b/sys/sys/vmmeter.h @@ -187,6 +187,13 @@ vm_page_count_severe(void) return (!DOMAINSET_EMPTY(&vm_severe_domains)); } +static inline int +vm_page_count_severe_set(domainset_t *mask) +{ + + return (DOMAINSET_SUBSET(&vm_severe_domains, mask)); +} + /* * Return TRUE if we are under our minimum low-free-pages threshold. * diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 6cbec2d151e6..636e8e67257e 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -484,8 +484,8 @@ static int doreallocblks = 1; SYSCTL_INT(_vfs_ffs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "enable block reallocation"); -static int dotrimcons = 0; -SYSCTL_INT(_vfs_ffs, OID_AUTO, dotrimcons, CTLFLAG_RW, &dotrimcons, 0, +static int dotrimcons = 1; +SYSCTL_INT(_vfs_ffs, OID_AUTO, dotrimcons, CTLFLAG_RWTUN, &dotrimcons, 0, "enable BIO_DELETE / TRIM consolidation"); static int maxclustersearch = 10; diff --git a/sys/vm/vm_domainset.c b/sys/vm/vm_domainset.c index eae083adade6..16b078e7dabd 100644 --- a/sys/vm/vm_domainset.c +++ b/sys/vm/vm_domainset.c @@ -100,6 +100,8 @@ vm_domainset_iter_init(struct vm_domainset_iter *di, struct vm_object *obj, pindex += (((uintptr_t)obj) / sizeof(*obj)); di->di_offset = pindex; } + /* Skip domains below min on the first pass. */ + di->di_minskip = true; } static void @@ -213,6 +215,8 @@ vm_domainset_iter_page_init(struct vm_domainset_iter *di, struct vm_object *obj, *req = (di->di_flags & ~(VM_ALLOC_WAITOK | VM_ALLOC_WAITFAIL)) | VM_ALLOC_NOWAIT; vm_domainset_iter_first(di, domain); + if (DOMAINSET_ISSET(*domain, &vm_min_domains)) + vm_domainset_iter_page(di, domain, req); } int @@ -227,8 +231,15 @@ vm_domainset_iter_page(struct vm_domainset_iter *di, int *domain, int *req) return (ENOMEM); /* If there are more domains to visit we run the iterator. */ - if (--di->di_n != 0) { + while (--di->di_n != 0) { vm_domainset_iter_next(di, domain); + if (!di->di_minskip || + !DOMAINSET_ISSET(*domain, &vm_min_domains)) + return (0); + } + if (di->di_minskip) { + di->di_minskip = false; + vm_domainset_iter_first(di, domain); return (0); } @@ -258,6 +269,8 @@ vm_domainset_iter_malloc_init(struct vm_domainset_iter *di, di->di_flags = *flags; *flags = (di->di_flags & ~M_WAITOK) | M_NOWAIT; vm_domainset_iter_first(di, domain); + if (DOMAINSET_ISSET(*domain, &vm_min_domains)) + vm_domainset_iter_malloc(di, domain, flags); } int @@ -265,8 +278,17 @@ vm_domainset_iter_malloc(struct vm_domainset_iter *di, int *domain, int *flags) { /* If there are more domains to visit we run the iterator. */ - if (--di->di_n != 0) { + while (--di->di_n != 0) { vm_domainset_iter_next(di, domain); + if (!di->di_minskip || + !DOMAINSET_ISSET(*domain, &vm_min_domains)) + return (0); + } + + /* If we skipped domains below min restart the search. */ + if (di->di_minskip) { + di->di_minskip = false; + vm_domainset_iter_first(di, domain); return (0); } diff --git a/sys/vm/vm_domainset.h b/sys/vm/vm_domainset.h index 542fe47da677..10da5caa0ea7 100644 --- a/sys/vm/vm_domainset.h +++ b/sys/vm/vm_domainset.h @@ -34,9 +34,10 @@ struct vm_domainset_iter { struct domainset *di_domain; int *di_iter; vm_pindex_t di_offset; - int di_policy; int di_flags; - int di_n; + uint16_t di_policy; + domainid_t di_n; + bool di_minskip; }; int vm_domainset_iter_page(struct vm_domainset_iter *, int *, int *); @@ -46,4 +47,6 @@ int vm_domainset_iter_malloc(struct vm_domainset_iter *, int *, int *); void vm_domainset_iter_malloc_init(struct vm_domainset_iter *, struct vm_object *, int *, int *); +void vm_wait_doms(const domainset_t *); + #endif /* __VM_DOMAINSET_H__ */ diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 9b8d90a423af..d5a6b57f47e3 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -548,6 +548,7 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, { struct faultstate fs; struct vnode *vp; + struct domainset *dset; vm_object_t next_object, retry_object; vm_offset_t e_end, e_start; vm_pindex_t retry_pindex; @@ -791,7 +792,11 @@ RetryFault:; * there, and allocation can fail, causing * restart and new reading of the p_flag. */ - if (!vm_page_count_severe() || P_KILLED(curproc)) { + dset = fs.object->domain.dr_policy; + if (dset == NULL) + dset = curthread->td_domain.dr_policy; + if (!vm_page_count_severe_set(&dset->ds_mask) || + P_KILLED(curproc)) { #if VM_NRESERVLEVEL > 0 vm_object_color(fs.object, atop(vaddr) - fs.pindex); @@ -806,7 +811,7 @@ RetryFault:; } if (fs.m == NULL) { unlock_and_deallocate(&fs); - vm_waitpfault(); + vm_waitpfault(dset); goto RetryFault; } } @@ -1124,7 +1129,7 @@ readrest: */ fs.object == fs.first_object->backing_object) { vm_page_lock(fs.m); - vm_page_remque(fs.m); + vm_page_dequeue(fs.m); vm_page_remove(fs.m); vm_page_unlock(fs.m); vm_page_lock(fs.first_m); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 7952c81a1afe..832dbce324ef 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> +#include <vm/vm_domainset.h> #include <vm/vm_map.h> #include <vm/vm_page.h> #include <vm/vm_pageout.h> @@ -534,6 +535,7 @@ vm_forkproc(struct thread *td, struct proc *p2, struct thread *td2, struct vmspace *vm2, int flags) { struct proc *p1 = td->td_proc; + struct domainset *dset; int error; if ((flags & RFPROC) == 0) { @@ -557,9 +559,9 @@ vm_forkproc(struct thread *td, struct proc *p2, struct thread *td2, p2->p_vmspace = p1->p_vmspace; atomic_add_int(&p1->p_vmspace->vm_refcnt, 1); } - - while (vm_page_count_severe()) { - vm_wait_severe(); + dset = td2->td_domain.dr_policy; + while (vm_page_count_severe_set(&dset->ds_mask)) { + vm_wait_doms(&dset->ds_mask); } if ((flags & RFMEM) == 0) { diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 8b25b86d0fcb..d022435704f1 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -2627,7 +2627,7 @@ retry: m_new->dirty = m->dirty; m->flags &= ~PG_ZERO; vm_page_xbusy(m); - vm_page_remque(m); + vm_page_dequeue(m); vm_page_replace_checked(m_new, object, m->pindex, m); if (vm_page_free_prep(m)) @@ -2642,7 +2642,7 @@ retry: vm_page_deactivate(m_new); } else { m->flags &= ~PG_ZERO; - vm_page_remque(m); + vm_page_dequeue(m); vm_page_remove(m); if (vm_page_free_prep(m)) SLIST_INSERT_HEAD(&free, m, @@ -2935,7 +2935,7 @@ vm_wait_count(void) return (vm_severe_waiters + vm_min_waiters + vm_pageproc_waiters); } -static void +void vm_wait_doms(const domainset_t *wdoms) { @@ -2961,10 +2961,10 @@ vm_wait_doms(const domainset_t *wdoms) mtx_lock(&vm_domainset_lock); if (DOMAINSET_SUBSET(&vm_min_domains, wdoms)) { vm_min_waiters++; - msleep(&vm_min_domains, &vm_domainset_lock, PVM, - "vmwait", 0); - } - mtx_unlock(&vm_domainset_lock); + msleep(&vm_min_domains, &vm_domainset_lock, + PVM | PDROP, "vmwait", 0); + } else + mtx_unlock(&vm_domainset_lock); } } @@ -3069,15 +3069,21 @@ vm_domain_alloc_fail(struct vm_domain *vmd, vm_object_t object, int req) * this balance without careful testing first. */ void -vm_waitpfault(void) +vm_waitpfault(struct domainset *dset) { + /* + * XXX Ideally we would wait only until the allocation could + * be satisfied. This condition can cause new allocators to + * consume all freed pages while old allocators wait. + */ mtx_lock(&vm_domainset_lock); - if (vm_page_count_min()) { + if (DOMAINSET_SUBSET(&vm_min_domains, &dset->ds_mask)) { vm_min_waiters++; - msleep(&vm_min_domains, &vm_domainset_lock, PUSER, "pfault", 0); - } - mtx_unlock(&vm_domainset_lock); + msleep(&vm_min_domains, &vm_domainset_lock, PUSER | PDROP, + "pfault", 0); + } else + mtx_unlock(&vm_domainset_lock); } struct vm_pagequeue * @@ -3101,28 +3107,35 @@ static inline void vm_pqbatch_process_page(struct vm_pagequeue *pq, vm_page_t m) { struct vm_domain *vmd; - uint8_t aflags; + uint8_t qflags; CRITICAL_ASSERT(curthread); vm_pagequeue_assert_locked(pq); - KASSERT(pq == vm_page_pagequeue(m), - ("page %p doesn't belong to %p", m, pq)); - aflags = m->aflags; - if ((aflags & PGA_DEQUEUE) != 0) { - if (__predict_true((aflags & PGA_ENQUEUED) != 0)) { + /* + * The page daemon is allowed to set m->queue = PQ_NONE without + * the page queue lock held. In this case it is about to free the page, + * which must not have any queue state. + */ + qflags = atomic_load_8(&m->aflags) & PGA_QUEUE_STATE_MASK; + KASSERT(pq == vm_page_pagequeue(m) || qflags == 0, + ("page %p doesn't belong to queue %p but has queue state %#x", + m, pq, qflags)); + + if ((qflags & PGA_DEQUEUE) != 0) { + if (__predict_true((qflags & PGA_ENQUEUED) != 0)) { TAILQ_REMOVE(&pq->pq_pl, m, plinks.q); vm_pagequeue_cnt_dec(pq); } vm_page_dequeue_complete(m); - } else if ((aflags & (PGA_REQUEUE | PGA_REQUEUE_HEAD)) != 0) { - if ((aflags & PGA_ENQUEUED) != 0) + } else if ((qflags & (PGA_REQUEUE | PGA_REQUEUE_HEAD)) != 0) { + if ((qflags & PGA_ENQUEUED) != 0) TAILQ_REMOVE(&pq->pq_pl, m, plinks.q); else { vm_pagequeue_cnt_inc(pq); vm_page_aflag_set(m, PGA_ENQUEUED); } - if ((aflags & PGA_REQUEUE_HEAD) != 0) { + if ((qflags & PGA_REQUEUE_HEAD) != 0) { KASSERT(m->queue == PQ_INACTIVE, ("head enqueue not supported for page %p", m)); vmd = vm_pagequeue_domain(m); @@ -3393,18 +3406,18 @@ vm_page_requeue(vm_page_t m) void vm_page_activate(vm_page_t m) { - int queue; vm_page_assert_locked(m); - if ((queue = vm_page_queue(m)) == PQ_ACTIVE || m->wire_count > 0 || - (m->oflags & VPO_UNMANAGED) != 0) { - if (queue == PQ_ACTIVE && m->act_count < ACT_INIT) + if (m->wire_count > 0 || (m->oflags & VPO_UNMANAGED) != 0) + return; + if (vm_page_queue(m) == PQ_ACTIVE) { + if (m->act_count < ACT_INIT) m->act_count = ACT_INIT; return; } - vm_page_remque(m); + vm_page_dequeue(m); if (m->act_count < ACT_INIT) m->act_count = ACT_INIT; vm_page_enqueue(m, PQ_ACTIVE); @@ -3676,7 +3689,7 @@ vm_page_deactivate(vm_page_t m) return; if (!vm_page_inactive(m)) { - vm_page_remque(m); + vm_page_dequeue(m); vm_page_enqueue(m, PQ_INACTIVE); } else vm_page_requeue(m); @@ -3699,9 +3712,10 @@ vm_page_deactivate_noreuse(vm_page_t m) if (m->wire_count > 0 || (m->oflags & VPO_UNMANAGED) != 0) return; - if (!vm_page_inactive(m)) - vm_page_remque(m); - m->queue = PQ_INACTIVE; + if (!vm_page_inactive(m)) { + vm_page_dequeue(m); + m->queue = PQ_INACTIVE; + } if ((m->aflags & PGA_REQUEUE_HEAD) == 0) vm_page_aflag_set(m, PGA_REQUEUE_HEAD); vm_pqbatch_submit_page(m, PQ_INACTIVE); @@ -3723,7 +3737,7 @@ vm_page_launder(vm_page_t m) if (vm_page_in_laundry(m)) vm_page_requeue(m); else { - vm_page_remque(m); + vm_page_dequeue(m); vm_page_enqueue(m, PQ_LAUNDRY); } } @@ -3741,7 +3755,7 @@ vm_page_unswappable(vm_page_t m) KASSERT(m->wire_count == 0 && (m->oflags & VPO_UNMANAGED) == 0, ("page %p already unswappable", m)); - vm_page_remque(m); + vm_page_dequeue(m); vm_page_enqueue(m, PQ_UNSWAPPABLE); } diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 73d289fd8b13..cf00912487ef 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -740,22 +740,6 @@ vm_page_dirty(vm_page_t m) } /* - * vm_page_remque: - * - * If the given page is in a page queue, then remove it from that page - * queue. - * - * The page must be locked. - */ -static inline void -vm_page_remque(vm_page_t m) -{ - - if (m->queue != PQ_NONE) - vm_page_dequeue(m); -} - -/* * vm_page_undirty: * * Set page to not be dirty. Note: does not clear pmap modify bits diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h index 935088f1f301..3b238a0ba3fb 100644 --- a/sys/vm/vm_pageout.h +++ b/sys/vm/vm_pageout.h @@ -96,7 +96,7 @@ extern int vm_pageout_page_count; */ void vm_wait(vm_object_t obj); -void vm_waitpfault(void); +void vm_waitpfault(struct domainset *); void vm_wait_domain(int domain); void vm_wait_min(void); void vm_wait_severe(void); diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c index 6f0440cfdc2d..890f5dad9213 100644 --- a/sys/vm/vm_phys.c +++ b/sys/vm/vm_phys.c @@ -460,7 +460,7 @@ void vm_phys_init(void) { struct vm_freelist *fl; - struct vm_phys_seg *seg; + struct vm_phys_seg *end_seg, *prev_seg, *seg, *tmp_seg; u_long npages; int dom, flind, freelist, oind, pind, segind; @@ -547,6 +547,29 @@ vm_phys_init(void) } /* + * Coalesce physical memory segments that are contiguous and share the + * same per-domain free queues. + */ + prev_seg = vm_phys_segs; + seg = &vm_phys_segs[1]; + end_seg = &vm_phys_segs[vm_phys_nsegs]; + while (seg < end_seg) { + if (prev_seg->end == seg->start && + prev_seg->free_queues == seg->free_queues) { + prev_seg->end = seg->end; + KASSERT(prev_seg->domain == seg->domain, + ("vm_phys_init: free queues cannot span domains")); + vm_phys_nsegs--; + end_seg--; + for (tmp_seg = seg; tmp_seg < end_seg; tmp_seg++) + *tmp_seg = *(tmp_seg + 1); + } else { + prev_seg = seg; + seg++; + } + } + + /* * Initialize the free queues. */ for (dom = 0; dom < vm_ndomains; dom++) { diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c index a879d616d17a..9f93ec96f837 100644 --- a/sys/x86/x86/intr_machdep.c +++ b/sys/x86/x86/intr_machdep.c @@ -173,8 +173,10 @@ intr_init_sources(void *arg) interrupt_sources = mallocarray(num_io_irqs, sizeof(*interrupt_sources), M_INTR, M_WAITOK | M_ZERO); +#ifdef SMP interrupt_sorted = mallocarray(num_io_irqs, sizeof(*interrupt_sorted), M_INTR, M_WAITOK | M_ZERO); +#endif /* * - 1 ??? dummy counter. |
