aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/include/vmm.h3
-rw-r--r--sys/amd64/pt/pt.c221
-rw-r--r--sys/amd64/vmm/vmm.c177
-rw-r--r--sys/arm/allwinner/aw_sid.c2
-rw-r--r--sys/arm/arm/elf_machdep.c4
-rw-r--r--sys/arm/ti/ti_pruss.c1
-rw-r--r--sys/arm64/arm64/cpu_errata.c96
-rw-r--r--sys/arm64/arm64/spec_workaround.c166
-rw-r--r--sys/arm64/include/vmm.h2
-rw-r--r--sys/arm64/vmm/vmm.c4
-rw-r--r--sys/cam/scsi/scsi_all.c2
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c6
-rw-r--r--sys/cam/scsi/scsi_pass.c3
-rw-r--r--sys/cam/scsi/scsi_target.c1
-rw-r--r--sys/compat/linprocfs/linprocfs.c77
-rw-r--r--sys/compat/linux/linux.c26
-rw-r--r--sys/compat/linux/linux_common.h2
-rw-r--r--sys/compat/linux/linux_event.c2
-rw-r--r--sys/compat/linux/linux_socket.c32
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c2
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/conf/files.arm641
-rw-r--r--sys/contrib/libnv/bsd_nvpair.c8
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/sysctl_os.c41
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c1
-rw-r--r--sys/crypto/chacha20/chacha.c6
-rw-r--r--sys/crypto/openssl/ossl_sha256.c4
-rw-r--r--sys/dev/ahci/ahciem.c2
-rw-r--r--sys/dev/aic7xxx/aic79xx.c4
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c4
-rw-r--r--sys/dev/atkbdc/psm.c1
-rw-r--r--sys/dev/cyapa/cyapa.c3
-rw-r--r--sys/dev/dc/if_dc.c2
-rw-r--r--sys/dev/enetc/if_enetc.c6
-rw-r--r--sys/dev/evdev/cdev.c1
-rw-r--r--sys/dev/evdev/uinput.c1
-rw-r--r--sys/dev/gpio/gpioc.c3
-rw-r--r--sys/dev/hid/hidraw.c1
-rw-r--r--sys/dev/hid/u2f.c1
-rw-r--r--sys/dev/hptmv/entry.c33
-rw-r--r--sys/dev/hptmv/gui_lib.c12
-rw-r--r--sys/dev/hptmv/hptproc.c2
-rw-r--r--sys/dev/ixl/if_ixl.c27
-rw-r--r--sys/dev/ixl/ixl.h1
-rw-r--r--sys/dev/ixl/ixl_pf_main.c110
-rw-r--r--sys/dev/mps/mps_sas.c4
-rw-r--r--sys/dev/mpt/mpt_raid.c4
-rw-r--r--sys/dev/netmap/netmap_freebsd.c18
-rw-r--r--sys/dev/nfe/if_nfe.c4
-rw-r--r--sys/dev/null/null.c6
-rw-r--r--sys/dev/ocs_fc/ocs_mgmt.c14
-rw-r--r--sys/dev/pci/controller/pci_n1sdp.c12
-rw-r--r--sys/dev/ppc/ppc.c2
-rw-r--r--sys/dev/qat/qat_common/adf_freebsd_dev_processes.c1
-rw-r--r--sys/dev/smartpqi/smartpqi_event.c6
-rw-r--r--sys/dev/smartpqi/smartpqi_queue.c4
-rw-r--r--sys/dev/sym/sym_hipd.c12
-rw-r--r--sys/dev/tws/tws.c13
-rw-r--r--sys/dev/tws/tws_services.c2
-rw-r--r--sys/dev/usb/usb_dev.c2
-rw-r--r--sys/dev/vmm/vmm_dev.c28
-rw-r--r--sys/fs/cuse/cuse.c2
-rw-r--r--sys/fs/devfs/devfs_dir.c2
-rw-r--r--sys/fs/fuse/fuse_device.c2
-rw-r--r--sys/fs/udf/osta.c4
-rw-r--r--sys/fs/unionfs/union_vnops.c10
-rw-r--r--sys/geom/geom_dev.c1
-rw-r--r--sys/i386/i386/elf_machdep.c12
-rw-r--r--sys/i386/i386/in_cksum_machdep.c2
-rw-r--r--sys/i386/linux/linux_sysvec.c12
-rw-r--r--sys/kern/imgact_elf.c12
-rw-r--r--sys/kern/kern_descrip.c55
-rw-r--r--sys/kern/kern_devctl.c1
-rw-r--r--sys/kern/kern_event.c267
-rw-r--r--sys/kern/kern_exit.c2
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_jaildesc.c1
-rw-r--r--sys/kern/kern_malloc.c2
-rw-r--r--sys/kern/kern_sig.c1
-rw-r--r--sys/kern/subr_devstat.c2
-rw-r--r--sys/kern/subr_log.c1
-rw-r--r--sys/kern/subr_prf.c2
-rw-r--r--sys/kern/sys_eventfd.c7
-rw-r--r--sys/kern/sys_pipe.c5
-rw-r--r--sys/kern/sys_procdesc.c1
-rw-r--r--sys/kern/tty.c2
-rw-r--r--sys/kern/tty_pts.c2
-rw-r--r--sys/kern/uipc_mqueue.c2
-rw-r--r--sys/kern/uipc_socket.c3
-rw-r--r--sys/kern/uipc_usrreq.c22
-rw-r--r--sys/kern/vfs_aio.c4
-rw-r--r--sys/kern/vfs_inotify.c1
-rw-r--r--sys/kern/vfs_subr.c15
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/net/bpf.c2
-rw-r--r--sys/net/if_tuntap.c2
-rw-r--r--sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c3
-rw-r--r--sys/netinet/in_mcast.c113
-rw-r--r--sys/netinet/libalias/alias_db.c2
-rw-r--r--sys/netinet/siftr.c2
-rw-r--r--sys/netinet/tcp_hpts_test.c20
-rw-r--r--sys/netinet/tcp_input.c2
-rw-r--r--sys/netinet/tcp_output.c2
-rw-r--r--sys/netinet/tcp_stacks/rack.c73
-rw-r--r--sys/netinet/tcp_syncache.c33
-rw-r--r--sys/netpfil/ipfw/ip_dummynet.c4
-rw-r--r--sys/powerpc/powerpc/elf32_machdep.c8
-rw-r--r--sys/powerpc/powerpc/elf64_machdep.c12
-rw-r--r--sys/riscv/include/vmm.h2
-rw-r--r--sys/riscv/riscv/elf_machdep.c4
-rw-r--r--sys/riscv/vmm/vmm.c4
-rw-r--r--sys/security/audit/audit_pipe.c1
-rw-r--r--sys/sys/event.h3
-rw-r--r--sys/sys/eventvar.h2
-rw-r--r--sys/sys/file.h4
-rw-r--r--sys/sys/filedesc.h2
-rw-r--r--sys/sys/imgact_elf.h6
-rw-r--r--sys/sys/sockbuf.h2
-rw-r--r--sys/sys/sockopt.h6
-rw-r--r--sys/sys/syscallsubr.h3
-rw-r--r--sys/vm/vm_domainset.c10
-rw-r--r--sys/vm/vm_glue.c24
-rw-r--r--sys/x86/acpica/acpi_apm.c1
123 files changed, 1429 insertions, 622 deletions
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index 66d8991d36e8..ad67510fecf3 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -237,7 +237,7 @@ extern u_int vm_maxcpu; /* maximum virtual cpus */
int vm_create(const char *name, struct vm **retvm);
struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
void vm_disable_vcpu_creation(struct vm *vm);
-void vm_slock_vcpus(struct vm *vm);
+void vm_lock_vcpus(struct vm *vm);
void vm_unlock_vcpus(struct vm *vm);
void vm_destroy(struct vm *vm);
int vm_reinit(struct vm *vm);
@@ -362,6 +362,7 @@ enum vcpu_state {
};
int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
+int vcpu_set_state_all(struct vm *vm, enum vcpu_state state);
enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
static int __inline
diff --git a/sys/amd64/pt/pt.c b/sys/amd64/pt/pt.c
index c7b75767680a..6b2296de049c 100644
--- a/sys/amd64/pt/pt.c
+++ b/sys/amd64/pt/pt.c
@@ -42,15 +42,15 @@
*/
#include <sys/systm.h>
+#include <sys/bus.h>
#include <sys/hwt.h>
+#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
-#include <sys/sdt.h>
#include <sys/smp.h>
-#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
@@ -94,12 +94,7 @@
MALLOC_DEFINE(M_PT, "pt", "Intel Processor Trace");
-SDT_PROVIDER_DEFINE(pt);
-SDT_PROBE_DEFINE(pt, , , topa__intr);
-
-TASKQUEUE_FAST_DEFINE_THREAD(pt);
-
-static void pt_send_buffer_record(void *arg, int pending __unused);
+static void pt_send_buffer_record(void *arg);
static int pt_topa_intr(struct trapframe *tf);
/*
@@ -122,29 +117,24 @@ struct pt_buffer {
size_t size;
struct mtx lock; /* Lock for fields below. */
vm_offset_t offset;
- uint64_t wrap_count;
- int curpage;
};
struct pt_ctx {
int id;
struct pt_buffer buf; /* ToPA buffer metadata */
- struct task task; /* ToPA buffer notification task */
struct hwt_context *hwt_ctx;
uint8_t *save_area; /* PT XSAVE area */
};
/* PT tracing contexts used for CPU mode. */
static struct pt_ctx *pt_pcpu_ctx;
-enum pt_cpu_state {
- PT_DISABLED = 0,
- PT_STOPPED,
- PT_ACTIVE
-};
+enum pt_cpu_state { PT_INACTIVE = 0, PT_ACTIVE };
static struct pt_cpu {
struct pt_ctx *ctx; /* active PT tracing context */
enum pt_cpu_state state; /* used as part of trace stop protocol */
+ void *swi_cookie; /* Software interrupt handler context */
+ int in_pcint_handler;
} *pt_pcpu;
/*
@@ -199,31 +189,28 @@ static __inline void
pt_update_buffer(struct pt_buffer *buf)
{
uint64_t reg;
- int curpage;
+ uint64_t offset;
/* Update buffer offset. */
reg = rdmsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS);
- curpage = (reg & PT_TOPA_PAGE_MASK) >> PT_TOPA_PAGE_SHIFT;
- mtx_lock_spin(&buf->lock);
- /* Check if the output wrapped. */
- if (buf->curpage > curpage)
- buf->wrap_count++;
- buf->curpage = curpage;
- buf->offset = reg >> 32;
- mtx_unlock_spin(&buf->lock);
-
- dprintf("%s: wrap_cnt: %lu, curpage: %d, offset: %zu\n", __func__,
- buf->wrap_count, buf->curpage, buf->offset);
+ offset = ((reg & PT_TOPA_PAGE_MASK) >> PT_TOPA_PAGE_SHIFT) * PAGE_SIZE;
+ offset += (reg >> 32);
+
+ atomic_store_rel_64(&buf->offset, offset);
}
static __inline void
pt_fill_buffer_record(int id, struct pt_buffer *buf,
struct hwt_record_entry *rec)
{
+ vm_offset_t offset;
+
+ offset = atomic_load_acq_64(&buf->offset);
+
rec->record_type = HWT_RECORD_BUFFER;
rec->buf_id = id;
- rec->curpage = buf->curpage;
- rec->offset = buf->offset + (buf->wrap_count * buf->size);
+ rec->curpage = offset / PAGE_SIZE;
+ rec->offset = offset & PAGE_MASK;
}
/*
@@ -273,9 +260,9 @@ pt_cpu_start(void *dummy)
MPASS(cpu->ctx != NULL);
dprintf("%s: curcpu %d\n", __func__, curcpu);
+ pt_cpu_set_state(curcpu, PT_ACTIVE);
load_cr4(rcr4() | CR4_XSAVE);
wrmsr(MSR_IA32_RTIT_STATUS, 0);
- pt_cpu_set_state(curcpu, PT_ACTIVE);
pt_cpu_toggle_local(cpu->ctx->save_area, true);
}
@@ -291,16 +278,16 @@ pt_cpu_stop(void *dummy)
struct pt_cpu *cpu;
struct pt_ctx *ctx;
- /* Shutdown may occur before PT gets properly configured. */
- if (pt_cpu_get_state(curcpu) == PT_DISABLED)
- return;
-
cpu = &pt_pcpu[curcpu];
ctx = cpu->ctx;
- MPASS(ctx != NULL);
- dprintf("%s: curcpu %d\n", __func__, curcpu);
- pt_cpu_set_state(curcpu, PT_STOPPED);
+ dprintf("%s: curcpu %d\n", __func__, curcpu);
+ /* Shutdown may occur before PT gets properly configured. */
+ if (ctx == NULL) {
+ dprintf("%s: missing context on cpu %d; bailing\n", __func__,
+ curcpu);
+ return;
+ }
pt_cpu_toggle_local(cpu->ctx->save_area, false);
pt_update_buffer(&ctx->buf);
}
@@ -406,13 +393,11 @@ pt_init_ctx(struct pt_ctx *pt_ctx, struct hwt_vm *vm, int ctx_id)
return (ENOMEM);
dprintf("%s: preparing ToPA buffer\n", __func__);
if (pt_topa_prepare(pt_ctx, vm) != 0) {
- dprintf("%s: failed to prepare ToPA buffer\n", __func__);
free(pt_ctx->save_area, M_PT);
return (ENOMEM);
}
pt_ctx->id = ctx_id;
- TASK_INIT(&pt_ctx->task, 0, pt_send_buffer_record, pt_ctx);
return (0);
}
@@ -426,7 +411,6 @@ pt_deinit_ctx(struct pt_ctx *pt_ctx)
if (pt_ctx->save_area != NULL)
free(pt_ctx->save_area, M_PT);
memset(pt_ctx, 0, sizeof(*pt_ctx));
- pt_ctx->buf.topa_hw = NULL;
}
/*
@@ -519,7 +503,6 @@ pt_backend_configure(struct hwt_context *ctx, int cpu_id, int thread_id)
XSTATE_XCOMP_BV_COMPACT;
pt_ext->rtit_ctl |= RTIT_CTL_TRACEEN;
pt_pcpu[cpu_id].ctx = pt_ctx;
- pt_cpu_set_state(cpu_id, PT_STOPPED);
return (0);
}
@@ -549,12 +532,19 @@ pt_backend_disable(struct hwt_context *ctx, int cpu_id)
if (ctx->mode == HWT_MODE_CPU)
return;
-
KASSERT(curcpu == cpu_id,
("%s: attempting to disable PT on another cpu", __func__));
+
+ cpu = &pt_pcpu[cpu_id];
+
+ dprintf("%s: waiting for cpu %d to exit interrupt handler\n", __func__,
+ cpu_id);
+ pt_cpu_set_state(cpu_id, PT_INACTIVE);
+ while (atomic_cmpset_int(&cpu->in_pcint_handler, 1, 0))
+ ;
+
pt_cpu_stop(NULL);
CPU_CLR(cpu_id, &ctx->cpu_map);
- cpu = &pt_pcpu[cpu_id];
cpu->ctx = NULL;
}
@@ -564,14 +554,14 @@ pt_backend_disable(struct hwt_context *ctx, int cpu_id)
static int
pt_backend_enable_smp(struct hwt_context *ctx)
{
-
dprintf("%s\n", __func__);
+
+ KASSERT(ctx->mode == HWT_MODE_CPU,
+ ("%s: should only be used for CPU mode", __func__));
if (ctx->mode == HWT_MODE_CPU &&
atomic_swap_32(&cpu_mode_ctr, 1) != 0)
return (-1);
- KASSERT(ctx->mode == HWT_MODE_CPU,
- ("%s: should only be used for CPU mode", __func__));
smp_rendezvous_cpus(ctx->cpu_map, NULL, pt_cpu_start, NULL, NULL);
return (0);
@@ -583,6 +573,7 @@ pt_backend_enable_smp(struct hwt_context *ctx)
static int
pt_backend_disable_smp(struct hwt_context *ctx)
{
+ struct pt_cpu *cpu;
dprintf("%s\n", __func__);
if (ctx->mode == HWT_MODE_CPU &&
@@ -593,6 +584,14 @@ pt_backend_disable_smp(struct hwt_context *ctx)
dprintf("%s: empty cpu map\n", __func__);
return (-1);
}
+ CPU_FOREACH_ISSET(cpu_id, &ctx->cpu_map) {
+ cpu = &pt_pcpu[cpu_id];
+ dprintf("%s: waiting for cpu %d to exit interrupt handler\n",
+ __func__, cpu_id);
+ pt_cpu_set_state(cpu_id, PT_INACTIVE);
+ while (atomic_cmpset_int(&cpu->in_pcint_handler, 1, 0))
+ ;
+ }
smp_rendezvous_cpus(ctx->cpu_map, NULL, pt_cpu_stop, NULL, NULL);
return (0);
@@ -611,13 +610,13 @@ pt_backend_init(struct hwt_context *ctx)
int error;
dprintf("%s\n", __func__);
- if (ctx->mode == HWT_MODE_CPU) {
- TAILQ_FOREACH(hwt_cpu, &ctx->cpus, next) {
- error = pt_init_ctx(&pt_pcpu_ctx[hwt_cpu->cpu_id],
- hwt_cpu->vm, hwt_cpu->cpu_id);
- if (error)
- return (error);
- }
+ if (ctx->mode != HWT_MODE_CPU)
+ return (0);
+ TAILQ_FOREACH(hwt_cpu, &ctx->cpus, next) {
+ error = pt_init_ctx(&pt_pcpu_ctx[hwt_cpu->cpu_id], hwt_cpu->vm,
+ hwt_cpu->cpu_id);
+ if (error)
+ return (error);
}
return (0);
@@ -647,20 +646,16 @@ pt_backend_deinit(struct hwt_context *ctx)
pt_deinit_ctx(pt_ctx);
}
} else {
- CPU_FOREACH(cpu_id) {
- if (!CPU_ISSET(cpu_id, &ctx->cpu_map))
+ CPU_FOREACH_ISSET(cpu_id, &ctx->cpu_map) {
+ if (pt_pcpu[cpu_id].ctx == NULL)
continue;
- if (pt_pcpu[cpu_id].ctx != NULL) {
- KASSERT(pt_pcpu[cpu_id].ctx ==
- &pt_pcpu_ctx[cpu_id],
- ("%s: CPU mode tracing with non-cpu mode PT"
- "context active",
- __func__));
- pt_pcpu[cpu_id].ctx = NULL;
- }
- pt_ctx = &pt_pcpu_ctx[cpu_id];
- pt_deinit_ctx(pt_ctx);
- memset(&pt_pcpu[cpu_id], 0, sizeof(struct pt_cpu));
+ KASSERT(pt_pcpu[cpu_id].ctx == &pt_pcpu_ctx[cpu_id],
+ ("%s: CPU mode tracing with non-cpu mode PT"
+ "context active",
+ __func__));
+ pt_deinit_ctx(pt_pcpu[cpu_id].ctx);
+ pt_pcpu[cpu_id].ctx = NULL;
+ atomic_set_int(&pt_pcpu[cpu_id].in_pcint_handler, 0);
}
}
@@ -675,15 +670,15 @@ pt_backend_read(struct hwt_vm *vm, int *curpage, vm_offset_t *curpage_offset,
uint64_t *data)
{
struct pt_buffer *buf;
+ uint64_t offset;
if (vm->ctx->mode == HWT_MODE_THREAD)
buf = &((struct pt_ctx *)vm->thr->private)->buf;
else
buf = &pt_pcpu[vm->cpu->cpu_id].ctx->buf;
- mtx_lock_spin(&buf->lock);
- *curpage = buf->curpage;
- *curpage_offset = buf->offset + (buf->wrap_count * vm->ctx->bufsize);
- mtx_unlock_spin(&buf->lock);
+ offset = atomic_load_acq_64(&buf->offset);
+ *curpage = offset / PAGE_SIZE;
+ *curpage_offset = offset & PAGE_MASK;
return (0);
}
@@ -762,15 +757,13 @@ static struct hwt_backend backend = {
* Used as a taskqueue routine from the ToPA interrupt handler.
*/
static void
-pt_send_buffer_record(void *arg, int pending __unused)
+pt_send_buffer_record(void *arg)
{
+ struct pt_cpu *cpu = (struct pt_cpu *)arg;
struct hwt_record_entry record;
- struct pt_ctx *ctx = (struct pt_ctx *)arg;
- /* Prepare buffer record. */
- mtx_lock_spin(&ctx->buf.lock);
+ struct pt_ctx *ctx = cpu->ctx;
pt_fill_buffer_record(ctx->id, &ctx->buf, &record);
- mtx_unlock_spin(&ctx->buf.lock);
hwt_record_ctx(ctx->hwt_ctx, &record, M_ZERO | M_NOWAIT);
}
static void
@@ -795,36 +788,40 @@ static int
pt_topa_intr(struct trapframe *tf)
{
struct pt_buffer *buf;
+ struct pt_cpu *cpu;
struct pt_ctx *ctx;
uint64_t reg;
- SDT_PROBE0(pt, , , topa__intr);
-
- if (pt_cpu_get_state(curcpu) != PT_ACTIVE) {
- return (0);
- }
+ cpu = &pt_pcpu[curcpu];
reg = rdmsr(MSR_IA_GLOBAL_STATUS);
if ((reg & GLOBAL_STATUS_FLAG_TRACETOPAPMI) == 0) {
- /* ACK spurious or leftover interrupt. */
pt_topa_status_clear();
+ return (0);
+ }
+
+ if (pt_cpu_get_state(curcpu) != PT_ACTIVE) {
return (1);
}
+ atomic_set_int(&cpu->in_pcint_handler, 1);
- ctx = pt_pcpu[curcpu].ctx;
+ ctx = cpu->ctx;
+ KASSERT(ctx != NULL,
+ ("%s: cpu %d: ToPA PMI interrupt without an active context",
+ __func__, curcpu));
buf = &ctx->buf;
KASSERT(buf->topa_hw != NULL,
- ("%s: ToPA PMI interrupt with invalid buffer", __func__));
-
+ ("%s: cpu %d: ToPA PMI interrupt with invalid buffer", __func__,
+ curcpu));
pt_cpu_toggle_local(ctx->save_area, false);
pt_update_buffer(buf);
pt_topa_status_clear();
- taskqueue_enqueue_flags(taskqueue_pt, &ctx->task,
- TASKQUEUE_FAIL_IF_PENDING);
if (pt_cpu_get_state(curcpu) == PT_ACTIVE) {
+ swi_sched(cpu->swi_cookie, SWI_FROMNMI);
pt_cpu_toggle_local(ctx->save_area, true);
lapic_reenable_pcint();
}
+ atomic_set_int(&cpu->in_pcint_handler, 0);
return (1);
}
@@ -839,7 +836,7 @@ static int
pt_init(void)
{
u_int cp[4];
- int error;
+ int error, i;
dprintf("pt: Enumerating part 1\n");
cpuid_count(CPUID_PT_LEAF, 0, cp);
@@ -869,20 +866,38 @@ pt_init(void)
pt_pcpu_ctx = mallocarray(mp_ncpus, sizeof(struct pt_ctx), M_PT,
M_ZERO | M_WAITOK);
+ for (i = 0; i < mp_ncpus; i++) {
+ error = swi_add(&clk_intr_event, "pt", pt_send_buffer_record,
+ &pt_pcpu[i], SWI_CLOCK, INTR_MPSAFE,
+ &pt_pcpu[i].swi_cookie);
+ if (error != 0) {
+ dprintf(
+ "%s: failed to add interrupt handler for cpu: %d\n",
+ __func__, error);
+ goto err;
+ }
+ }
+
nmi_register_handler(pt_topa_intr);
- if (!lapic_enable_pcint()) {
- nmi_remove_handler(pt_topa_intr);
- hwt_backend_unregister(&backend);
- free(pt_pcpu, M_PT);
- free(pt_pcpu_ctx, M_PT);
- pt_pcpu = NULL;
- pt_pcpu_ctx = NULL;
+ if (lapic_enable_pcint()) {
+ initialized = true;
+ return (0);
+ } else
printf("pt: failed to setup interrupt line\n");
- return (error);
+err:
+ nmi_remove_handler(pt_topa_intr);
+ hwt_backend_unregister(&backend);
+
+ for (i = 0; i < mp_ncpus; i++) {
+ if (pt_pcpu[i].swi_cookie != 0)
+ swi_remove(pt_pcpu[i].swi_cookie);
}
- initialized = true;
+ free(pt_pcpu, M_PT);
+ free(pt_pcpu_ctx, M_PT);
+ pt_pcpu = NULL;
+ pt_pcpu_ctx = NULL;
- return (0);
+ return (error);
}
/*
@@ -941,14 +956,24 @@ pt_supported(void)
static void
pt_deinit(void)
{
+ int i;
+ struct pt_cpu *cpu;
+
if (!initialized)
return;
nmi_remove_handler(pt_topa_intr);
lapic_disable_pcint();
hwt_backend_unregister(&backend);
+
+ for (i = 0; i < mp_ncpus; i++) {
+ cpu = &pt_pcpu[i];
+ swi_remove(cpu->swi_cookie);
+ }
+
free(pt_pcpu, M_PT);
free(pt_pcpu_ctx, M_PT);
pt_pcpu = NULL;
+ pt_pcpu_ctx = NULL;
initialized = false;
}
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 2ac076551165..f7c59847140b 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -562,9 +562,9 @@ vm_alloc_vcpu(struct vm *vm, int vcpuid)
}
void
-vm_slock_vcpus(struct vm *vm)
+vm_lock_vcpus(struct vm *vm)
{
- sx_slock(&vm->vcpus_init_lock);
+ sx_xlock(&vm->vcpus_init_lock);
}
void
@@ -990,6 +990,54 @@ save_guest_fpustate(struct vcpu *vcpu)
static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle");
+/*
+ * Invoke the rendezvous function on the specified vcpu if applicable. Return
+ * true if the rendezvous is finished, false otherwise.
+ */
+static bool
+vm_rendezvous(struct vcpu *vcpu)
+{
+ struct vm *vm = vcpu->vm;
+ int vcpuid;
+
+ mtx_assert(&vcpu->vm->rendezvous_mtx, MA_OWNED);
+ KASSERT(vcpu->vm->rendezvous_func != NULL,
+ ("vm_rendezvous: no rendezvous pending"));
+
+ /* 'rendezvous_req_cpus' must be a subset of 'active_cpus' */
+ CPU_AND(&vm->rendezvous_req_cpus, &vm->rendezvous_req_cpus,
+ &vm->active_cpus);
+
+ vcpuid = vcpu->vcpuid;
+ if (CPU_ISSET(vcpuid, &vm->rendezvous_req_cpus) &&
+ !CPU_ISSET(vcpuid, &vm->rendezvous_done_cpus)) {
+ VMM_CTR0(vcpu, "Calling rendezvous func");
+ (*vm->rendezvous_func)(vcpu, vm->rendezvous_arg);
+ CPU_SET(vcpuid, &vm->rendezvous_done_cpus);
+ }
+ if (CPU_CMP(&vm->rendezvous_req_cpus,
+ &vm->rendezvous_done_cpus) == 0) {
+ VMM_CTR0(vcpu, "Rendezvous completed");
+ CPU_ZERO(&vm->rendezvous_req_cpus);
+ vm->rendezvous_func = NULL;
+ wakeup(&vm->rendezvous_func);
+ return (true);
+ }
+ return (false);
+}
+
+static void
+vcpu_wait_idle(struct vcpu *vcpu)
+{
+ KASSERT(vcpu->state != VCPU_IDLE, ("vcpu already idle"));
+
+ vcpu->reqidle = 1;
+ vcpu_notify_event_locked(vcpu, false);
+ VMM_CTR1(vcpu, "vcpu state change from %s to "
+ "idle requested", vcpu_state2str(vcpu->state));
+ msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz);
+}
+
static int
vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
bool from_idle)
@@ -1004,13 +1052,8 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
* ioctl() operating on a vcpu at any point.
*/
if (from_idle) {
- while (vcpu->state != VCPU_IDLE) {
- vcpu->reqidle = 1;
- vcpu_notify_event_locked(vcpu, false);
- VMM_CTR1(vcpu, "vcpu state change from %s to "
- "idle requested", vcpu_state2str(vcpu->state));
- msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz);
- }
+ while (vcpu->state != VCPU_IDLE)
+ vcpu_wait_idle(vcpu);
} else {
KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from "
"vcpu idle state"));
@@ -1062,6 +1105,95 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
return (0);
}
+/*
+ * Try to lock all of the vCPUs in the VM while taking care to avoid deadlocks
+ * with vm_smp_rendezvous().
+ *
+ * The complexity here suggests that the rendezvous mechanism needs a rethink.
+ */
+int
+vcpu_set_state_all(struct vm *vm, enum vcpu_state newstate)
+{
+ cpuset_t locked;
+ struct vcpu *vcpu;
+ int error, i;
+ uint16_t maxcpus;
+
+ KASSERT(newstate != VCPU_IDLE,
+ ("vcpu_set_state_all: invalid target state %d", newstate));
+
+ error = 0;
+ CPU_ZERO(&locked);
+ maxcpus = vm->maxcpus;
+
+ mtx_lock(&vm->rendezvous_mtx);
+restart:
+ if (vm->rendezvous_func != NULL) {
+ /*
+ * If we have a pending rendezvous, then the initiator may be
+ * blocked waiting for other vCPUs to execute the callback. The
+ * current thread may be a vCPU thread so we must not block
+ * waiting for the initiator, otherwise we get a deadlock.
+ * Thus, execute the callback on behalf of any idle vCPUs.
+ */
+ for (i = 0; i < maxcpus; i++) {
+ vcpu = vm_vcpu(vm, i);
+ if (vcpu == NULL)
+ continue;
+ vcpu_lock(vcpu);
+ if (vcpu->state == VCPU_IDLE) {
+ (void)vcpu_set_state_locked(vcpu, VCPU_FROZEN,
+ true);
+ CPU_SET(i, &locked);
+ }
+ if (CPU_ISSET(i, &locked)) {
+ /*
+ * We can safely execute the callback on this
+ * vCPU's behalf.
+ */
+ vcpu_unlock(vcpu);
+ (void)vm_rendezvous(vcpu);
+ vcpu_lock(vcpu);
+ }
+ vcpu_unlock(vcpu);
+ }
+ }
+
+ /*
+ * Now wait for remaining vCPUs to become idle. This may include the
+ * initiator of a rendezvous that is currently blocked on the rendezvous
+ * mutex.
+ */
+ CPU_FOREACH_ISCLR(i, &locked) {
+ if (i >= maxcpus)
+ break;
+ vcpu = vm_vcpu(vm, i);
+ if (vcpu == NULL)
+ continue;
+ vcpu_lock(vcpu);
+ while (vcpu->state != VCPU_IDLE) {
+ mtx_unlock(&vm->rendezvous_mtx);
+ vcpu_wait_idle(vcpu);
+ vcpu_unlock(vcpu);
+ mtx_lock(&vm->rendezvous_mtx);
+ if (vm->rendezvous_func != NULL)
+ goto restart;
+ vcpu_lock(vcpu);
+ }
+ error = vcpu_set_state_locked(vcpu, newstate, true);
+ vcpu_unlock(vcpu);
+ if (error != 0) {
+ /* Roll back state changes. */
+ CPU_FOREACH_ISSET(i, &locked)
+ (void)vcpu_set_state(vcpu, VCPU_IDLE, false);
+ break;
+ }
+ CPU_SET(i, &locked);
+ }
+ mtx_unlock(&vm->rendezvous_mtx);
+ return (error);
+}
+
static void
vcpu_require_state(struct vcpu *vcpu, enum vcpu_state newstate)
{
@@ -1083,36 +1215,23 @@ vcpu_require_state_locked(struct vcpu *vcpu, enum vcpu_state newstate)
static int
vm_handle_rendezvous(struct vcpu *vcpu)
{
- struct vm *vm = vcpu->vm;
+ struct vm *vm;
struct thread *td;
- int error, vcpuid;
- error = 0;
- vcpuid = vcpu->vcpuid;
td = curthread;
+ vm = vcpu->vm;
+
mtx_lock(&vm->rendezvous_mtx);
while (vm->rendezvous_func != NULL) {
- /* 'rendezvous_req_cpus' must be a subset of 'active_cpus' */
- CPU_AND(&vm->rendezvous_req_cpus, &vm->rendezvous_req_cpus, &vm->active_cpus);
-
- if (CPU_ISSET(vcpuid, &vm->rendezvous_req_cpus) &&
- !CPU_ISSET(vcpuid, &vm->rendezvous_done_cpus)) {
- VMM_CTR0(vcpu, "Calling rendezvous func");
- (*vm->rendezvous_func)(vcpu, vm->rendezvous_arg);
- CPU_SET(vcpuid, &vm->rendezvous_done_cpus);
- }
- if (CPU_CMP(&vm->rendezvous_req_cpus,
- &vm->rendezvous_done_cpus) == 0) {
- VMM_CTR0(vcpu, "Rendezvous completed");
- CPU_ZERO(&vm->rendezvous_req_cpus);
- vm->rendezvous_func = NULL;
- wakeup(&vm->rendezvous_func);
+ if (vm_rendezvous(vcpu))
break;
- }
+
VMM_CTR0(vcpu, "Wait for rendezvous completion");
mtx_sleep(&vm->rendezvous_func, &vm->rendezvous_mtx, 0,
"vmrndv", hz);
if (td_ast_pending(td, TDA_SUSPEND)) {
+ int error;
+
mtx_unlock(&vm->rendezvous_mtx);
error = thread_check_susp(td, true);
if (error != 0)
diff --git a/sys/arm/allwinner/aw_sid.c b/sys/arm/allwinner/aw_sid.c
index ba5faca33c5e..932c2f189e51 100644
--- a/sys/arm/allwinner/aw_sid.c
+++ b/sys/arm/allwinner/aw_sid.c
@@ -297,7 +297,7 @@ aw_sid_attach(device_t dev)
/* Register ourself so device can resolve who we are */
OF_device_register_xref(OF_xref_from_node(node), dev);
- for (i = 0; i < sc->sid_conf->nfuses ;i++) {\
+ for (i = 0; i < sc->sid_conf->nfuses; i++) {
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
OID_AUTO, sc->sid_conf->efuses[i].name,
diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index ea6437f320ce..881c4fcff475 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -106,7 +106,7 @@ struct sysentvec elf32_freebsd_sysvec = {
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
-static Elf32_Brandinfo freebsd_brand_info = {
+static const Elf32_Brandinfo freebsd_brand_info = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_ARM,
.compat_3_brand = "FreeBSD",
@@ -118,7 +118,7 @@ static Elf32_Brandinfo freebsd_brand_info = {
.header_supported= elf32_arm_abi_supported,
};
-SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+C_SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
diff --git a/sys/arm/ti/ti_pruss.c b/sys/arm/ti/ti_pruss.c
index 4e9f2022240c..bae1de9f2ddf 100644
--- a/sys/arm/ti/ti_pruss.c
+++ b/sys/arm/ti/ti_pruss.c
@@ -793,6 +793,7 @@ static const struct filterops ti_pruss_kq_read = {
.f_isfd = 1,
.f_detach = ti_pruss_irq_kqread_detach,
.f_event = ti_pruss_irq_kqevent,
+ .f_copy = knote_triv_copy,
};
static void
diff --git a/sys/arm64/arm64/cpu_errata.c b/sys/arm64/arm64/cpu_errata.c
index 989924bc0567..b876703a2a15 100644
--- a/sys/arm64/arm64/cpu_errata.c
+++ b/sys/arm64/arm64/cpu_errata.c
@@ -52,56 +52,11 @@ struct cpu_quirks {
u_int flags;
};
-static enum {
- SSBD_FORCE_ON,
- SSBD_FORCE_OFF,
- SSBD_KERNEL,
-} ssbd_method = SSBD_KERNEL;
-
-static cpu_quirk_install install_psci_bp_hardening;
-static cpu_quirk_install install_ssbd_workaround;
static cpu_quirk_install install_thunderx_bcast_tlbi_workaround;
static struct cpu_quirks cpu_quirks[] = {
{
.midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
- .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A57,0,0),
- .quirk_install = install_psci_bp_hardening,
- .flags = CPU_QUIRK_POST_DEVICE,
- },
- {
- .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
- .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A72,0,0),
- .quirk_install = install_psci_bp_hardening,
- .flags = CPU_QUIRK_POST_DEVICE,
- },
- {
- .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
- .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A73,0,0),
- .quirk_install = install_psci_bp_hardening,
- .flags = CPU_QUIRK_POST_DEVICE,
- },
- {
- .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
- .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A75,0,0),
- .quirk_install = install_psci_bp_hardening,
- .flags = CPU_QUIRK_POST_DEVICE,
- },
- {
- .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
- .midr_value =
- CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0,0),
- .quirk_install = install_psci_bp_hardening,
- .flags = CPU_QUIRK_POST_DEVICE,
- },
- {
- .midr_mask = 0,
- .midr_value = 0,
- .quirk_install = install_ssbd_workaround,
- .flags = CPU_QUIRK_POST_DEVICE,
- },
- {
- .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
.midr_value =
CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDERX, 0, 0),
.quirk_install = install_thunderx_bcast_tlbi_workaround,
@@ -114,57 +69,6 @@ static struct cpu_quirks cpu_quirks[] = {
},
};
-static void
-install_psci_bp_hardening(void)
-{
- /* SMCCC depends on PSCI. If PSCI is missing so is SMCCC */
- if (!psci_present)
- return;
-
- if (smccc_arch_features(SMCCC_ARCH_WORKAROUND_1) != SMCCC_RET_SUCCESS)
- return;
-
- PCPU_SET(bp_harden, smccc_arch_workaround_1);
-}
-
-static void
-install_ssbd_workaround(void)
-{
- char *env;
-
- if (PCPU_GET(cpuid) == 0) {
- env = kern_getenv("kern.cfg.ssbd");
- if (env != NULL) {
- if (strcmp(env, "force-on") == 0) {
- ssbd_method = SSBD_FORCE_ON;
- } else if (strcmp(env, "force-off") == 0) {
- ssbd_method = SSBD_FORCE_OFF;
- }
- }
- }
-
- /* SMCCC depends on PSCI. If PSCI is missing so is SMCCC */
- if (!psci_present)
- return;
-
- /* Enable the workaround on this CPU if it's enabled in the firmware */
- if (smccc_arch_features(SMCCC_ARCH_WORKAROUND_2) != SMCCC_RET_SUCCESS)
- return;
-
- switch(ssbd_method) {
- case SSBD_FORCE_ON:
- smccc_arch_workaround_2(1);
- break;
- case SSBD_FORCE_OFF:
- smccc_arch_workaround_2(0);
- break;
- case SSBD_KERNEL:
- default:
- PCPU_SET(ssbd, smccc_arch_workaround_2);
- break;
- }
-}
-
/*
* Workaround Cavium erratum 27456.
*
diff --git a/sys/arm64/arm64/spec_workaround.c b/sys/arm64/arm64/spec_workaround.c
new file mode 100644
index 000000000000..7f4f86cdb48c
--- /dev/null
+++ b/sys/arm64/arm64/spec_workaround.c
@@ -0,0 +1,166 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Arm Ltd
+ * Copyright (c) 2018 Andrew Turner
+ *
+ * This software was 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.
+ *
+ * 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/kernel.h>
+#include <sys/pcpu.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/cpu_feat.h>
+
+#include <dev/psci/psci.h>
+#include <dev/psci/smccc.h>
+
+static enum {
+ SSBD_FORCE_ON,
+ SSBD_FORCE_OFF,
+ SSBD_KERNEL,
+} ssbd_method = SSBD_KERNEL;
+
+struct psci_bp_hardening_impl {
+ u_int midr_mask;
+ u_int midr_value;
+};
+
+static struct psci_bp_hardening_impl psci_bp_hardening_impl[] = {
+ {
+ .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
+ .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A57,0,0),
+ },
+ {
+ .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
+ .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A72,0,0),
+ },
+ {
+ .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
+ .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A73,0,0),
+ },
+ {
+ .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
+ .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A75,0,0),
+ },
+ {
+ .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK,
+ .midr_value =
+ CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0,0),
+ }
+};
+
+static cpu_feat_en
+psci_bp_hardening_check(const struct cpu_feat *feat __unused, u_int midr)
+{
+ size_t i;
+
+ for (i = 0; i < nitems(psci_bp_hardening_impl); i++) {
+ if ((midr & psci_bp_hardening_impl[i].midr_mask) ==
+ psci_bp_hardening_impl[i].midr_value) {
+ /* SMCCC depends on PSCI. If PSCI is missing so is SMCCC */
+ if (!psci_present)
+ return (FEAT_ALWAYS_DISABLE);
+
+ if (smccc_arch_features(SMCCC_ARCH_WORKAROUND_1) !=
+ SMCCC_RET_SUCCESS)
+ return (FEAT_ALWAYS_DISABLE);
+
+ return (FEAT_DEFAULT_ENABLE);
+ }
+ }
+
+ return (FEAT_ALWAYS_DISABLE);
+}
+
+static bool
+psci_bp_hardening_enable(const struct cpu_feat *feat __unused,
+ cpu_feat_errata errata_status __unused, u_int *errata_list __unused,
+ u_int errata_count __unused)
+{
+ PCPU_SET(bp_harden, smccc_arch_workaround_1);
+
+ return (true);
+}
+
+CPU_FEAT(feat_csv2_missing, "Branch Predictor Hardening",
+ psci_bp_hardening_check, NULL, psci_bp_hardening_enable, NULL,
+ CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU);
+
+static cpu_feat_en
+ssbd_workaround_check(const struct cpu_feat *feat __unused, u_int midr __unused)
+{
+ char *env;
+
+ if (PCPU_GET(cpuid) == 0) {
+ env = kern_getenv("kern.cfg.ssbd");
+ if (env != NULL) {
+ if (strcmp(env, "force-on") == 0) {
+ ssbd_method = SSBD_FORCE_ON;
+ } else if (strcmp(env, "force-off") == 0) {
+ ssbd_method = SSBD_FORCE_OFF;
+ }
+ }
+ }
+
+ /* SMCCC depends on PSCI. If PSCI is missing so is SMCCC */
+ if (!psci_present)
+ return (FEAT_ALWAYS_DISABLE);
+
+ /* Enable the workaround on this CPU if it's enabled in the firmware */
+ if (smccc_arch_features(SMCCC_ARCH_WORKAROUND_2) != SMCCC_RET_SUCCESS)
+ return (FEAT_ALWAYS_DISABLE);
+
+ return (FEAT_DEFAULT_ENABLE);
+}
+
+static bool
+ssbd_workaround_enable(const struct cpu_feat *feat __unused,
+ cpu_feat_errata errata_status __unused, u_int *errata_list __unused,
+ u_int errata_count __unused)
+{
+ switch(ssbd_method) {
+ case SSBD_FORCE_ON:
+ smccc_arch_workaround_2(1);
+ break;
+ case SSBD_FORCE_OFF:
+ smccc_arch_workaround_2(0);
+ break;
+ case SSBD_KERNEL:
+ default:
+ PCPU_SET(ssbd, smccc_arch_workaround_2);
+ break;
+ }
+
+ return (true);
+}
+
+CPU_FEAT(feat_ssbs_missing, "Speculator Store Bypass Disable Workaround",
+ ssbd_workaround_check, NULL, ssbd_workaround_enable, NULL,
+ CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU);
diff --git a/sys/arm64/include/vmm.h b/sys/arm64/include/vmm.h
index 84b286a60b38..696a69669a2a 100644
--- a/sys/arm64/include/vmm.h
+++ b/sys/arm64/include/vmm.h
@@ -177,7 +177,7 @@ DECLARE_VMMOPS_FUNC(int, restore_tsc, (void *vcpui, uint64_t now));
int vm_create(const char *name, struct vm **retvm);
struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
void vm_disable_vcpu_creation(struct vm *vm);
-void vm_slock_vcpus(struct vm *vm);
+void vm_lock_vcpus(struct vm *vm);
void vm_unlock_vcpus(struct vm *vm);
void vm_destroy(struct vm *vm);
int vm_reinit(struct vm *vm);
diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c
index aeda689f3b1a..bf52dc0fe916 100644
--- a/sys/arm64/vmm/vmm.c
+++ b/sys/arm64/vmm/vmm.c
@@ -469,9 +469,9 @@ vm_alloc_vcpu(struct vm *vm, int vcpuid)
}
void
-vm_slock_vcpus(struct vm *vm)
+vm_lock_vcpus(struct vm *vm)
{
- sx_slock(&vm->vcpus_init_lock);
+ sx_xlock(&vm->vcpus_init_lock);
}
void
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index 9c097f52d136..fd128e69f1f1 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -686,7 +686,7 @@ scsi_op_desc(uint16_t opcode, struct scsi_inquiry_data *inq_data)
opmask = 1 << pd_type;
for (j = 0; j < num_tables; j++) {
- for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){
+ for (i = 0; i < num_ops[j] && table[j][i].opcode <= opcode; i++) {
if ((table[j][i].opcode == opcode)
&& ((table[j][i].opmask & opmask) != 0))
return(table[j][i].desc);
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 435874a9874a..3a362eaf11a4 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -2302,7 +2302,7 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
sbuf_putc(sbp, '\n');
if (addl->proto_data.sasdev_phys == NULL)
return;
- for (i = 0;i < addl->proto_hdr.sas->base_hdr.num_phys;i++) {
+ for (i = 0; i < addl->proto_hdr.sas->base_hdr.num_phys; i++) {
phy = &addl->proto_data.sasdev_phys[i];
sbuf_printf(sbp, "%s: phy %d:", sesname, i);
if (ses_elm_sas_dev_phy_sata_dev(phy))
@@ -2349,7 +2349,7 @@ ses_print_addl_data_sas_type1(char *sesname, struct sbuf *sbp,
sbuf_printf(sbp, "Expander: %d phys", num_phys);
if (addl->proto_data.sasexp_phys == NULL)
return;
- for (i = 0;i < num_phys;i++) {
+ for (i = 0; i < num_phys; i++) {
exp_phy = &addl->proto_data.sasexp_phys[i];
sbuf_printf(sbp, "%s: phy %d: connector %d other %d\n",
sesname, i, exp_phy->connector_index,
@@ -2360,7 +2360,7 @@ ses_print_addl_data_sas_type1(char *sesname, struct sbuf *sbp,
sbuf_printf(sbp, "Port: %d phys", num_phys);
if (addl->proto_data.sasport_phys == NULL)
return;
- for (i = 0;i < num_phys;i++) {
+ for (i = 0; i < num_phys; i++) {
port_phy = &addl->proto_data.sasport_phys[i];
sbuf_printf(sbp,
"%s: phy %d: id %d connector %d other %d\n",
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index c3587421c176..b44ab866dfe7 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -206,7 +206,8 @@ static struct cdevsw pass_cdevsw = {
static const struct filterops passread_filtops = {
.f_isfd = 1,
.f_detach = passreadfiltdetach,
- .f_event = passreadfilt
+ .f_event = passreadfilt,
+ .f_copy = knote_triv_copy,
};
static MALLOC_DEFINE(M_SCSIPASS, "scsi_pass", "scsi passthrough buffers");
diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c
index 21c78e35dadc..39ce2bcea8f4 100644
--- a/sys/cam/scsi/scsi_target.c
+++ b/sys/cam/scsi/scsi_target.c
@@ -108,6 +108,7 @@ static const struct filterops targread_filtops = {
.f_isfd = 1,
.f_detach = targreadfiltdetach,
.f_event = targreadfilt,
+ .f_copy = knote_triv_copy,
};
static struct cdevsw targ_cdevsw = {
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 95b212be1306..7ac48786c77b 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -2216,6 +2216,67 @@ linprocfs_dosysvipc_shm(PFS_FILL_ARGS)
return (0);
}
+static int
+linprocfs_doinotify(const char *sysctl, PFS_FILL_ARGS)
+{
+ size_t size;
+ int error, val;
+
+ if (uio->uio_rw == UIO_READ) {
+ size = sizeof(val);
+ error = kernel_sysctlbyname(curthread,
+ __DECONST(void *, sysctl), &val, &size, NULL, 0, 0, 0);
+ if (error == 0)
+ sbuf_printf(sb, "%d\n", val);
+ } else {
+ char *endp, *newval;
+ long vall;
+
+ sbuf_trim(sb);
+ sbuf_finish(sb);
+ newval = sbuf_data(sb);
+ vall = strtol(newval, &endp, 10);
+ if (vall < 0 || vall > INT_MAX || endp == newval ||
+ *endp != '\0')
+ return (EINVAL);
+ val = (int)vall;
+ error = kernel_sysctlbyname(curthread,
+ __DECONST(void *, sysctl), NULL, NULL,
+ &val, sizeof(val), 0, 0);
+ }
+ return (error);
+}
+
+/*
+ * Filler function for proc/sys/fs/inotify/max_queued_events
+ */
+static int
+linprocfs_doinotify_max_queued_events(PFS_FILL_ARGS)
+{
+ return (linprocfs_doinotify("vfs.inotify.max_queued_events",
+ PFS_FILL_ARGNAMES));
+}
+
+/*
+ * Filler function for proc/sys/fs/inotify/max_user_instances
+ */
+static int
+linprocfs_doinotify_max_user_instances(PFS_FILL_ARGS)
+{
+ return (linprocfs_doinotify("vfs.inotify.max_user_instances",
+ PFS_FILL_ARGNAMES));
+}
+
+/*
+ * Filler function for proc/sys/fs/inotify/max_user_watches
+ */
+static int
+linprocfs_doinotify_max_user_watches(PFS_FILL_ARGS)
+{
+ return (linprocfs_doinotify("vfs.inotify.max_user_watches",
+ PFS_FILL_ARGNAMES));
+}
+
/*
* Filler function for proc/sys/fs/mqueue/msg_default
*/
@@ -2313,9 +2374,7 @@ linprocfs_domqueue_queues_max(PFS_FILL_ARGS)
static int
linprocfs_init(PFS_INIT_ARGS)
{
- struct pfs_node *root;
- struct pfs_node *dir;
- struct pfs_node *sys;
+ struct pfs_node *dir, *fs, *root, *sys;
root = pi->pi_root;
@@ -2466,10 +2525,18 @@ linprocfs_init(PFS_INIT_ARGS)
NULL, PFS_RD);
/* /proc/sys/fs/... */
- pfs_create_dir(sys, &dir, "fs", NULL, NULL, NULL, 0);
+ pfs_create_dir(sys, &fs, "fs", NULL, NULL, NULL, 0);
+
+ pfs_create_dir(fs, &dir, "inotify", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "max_queued_events",
+ &linprocfs_doinotify_max_queued_events, NULL, NULL, NULL, PFS_RDWR);
+ pfs_create_file(dir, NULL, "max_user_instances",
+ &linprocfs_doinotify_max_user_instances, NULL, NULL, NULL, PFS_RDWR);
+ pfs_create_file(dir, NULL, "max_user_watches",
+ &linprocfs_doinotify_max_user_watches, NULL, NULL, NULL, PFS_RDWR);
/* /proc/sys/fs/mqueue/... */
- pfs_create_dir(dir, &dir, "mqueue", NULL, NULL, NULL, 0);
+ pfs_create_dir(fs, &dir, "mqueue", NULL, NULL, NULL, 0);
pfs_create_file(dir, NULL, "msg_default",
&linprocfs_domqueue_msg_default, NULL, NULL, NULL, PFS_RD);
pfs_create_file(dir, NULL, "msgsize_default",
diff --git a/sys/compat/linux/linux.c b/sys/compat/linux/linux.c
index 61b207070963..a40f110634f7 100644
--- a/sys/compat/linux/linux.c
+++ b/sys/compat/linux/linux.c
@@ -578,8 +578,13 @@ bsd_to_linux_sockaddr(const struct sockaddr *sa, struct l_sockaddr **lsa,
return (0);
}
+/*
+ * If sap is NULL, then osa points at already copied in linux sockaddr that
+ * should be edited in place. Otherwise memory is allocated, sockaddr
+ * copied in and returned in *sap.
+ */
int
-linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap,
+linux_to_bsd_sockaddr(struct l_sockaddr *osa, struct sockaddr **sap,
socklen_t *len)
{
struct sockaddr *sa;
@@ -609,10 +614,12 @@ linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap,
}
#endif
- kosa = malloc(salen, M_SONAME, M_WAITOK);
-
- if ((error = copyin(osa, kosa, *len)))
- goto out;
+ if (sap != NULL) {
+ kosa = malloc(salen, M_SONAME, M_WAITOK);
+ if ((error = copyin(osa, kosa, *len)))
+ goto out;
+ } else
+ kosa = osa;
bdom = linux_to_bsd_domain(kosa->sa_family);
if (bdom == AF_UNKNOWN) {
@@ -686,12 +693,15 @@ linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap,
sa->sa_family = bdom;
sa->sa_len = salen;
- *sap = sa;
- *len = salen;
+ if (sap != NULL) {
+ *sap = sa;
+ *len = salen;
+ }
return (0);
out:
- free(kosa, M_SONAME);
+ if (sap != NULL)
+ free(kosa, M_SONAME);
return (error);
}
diff --git a/sys/compat/linux/linux_common.h b/sys/compat/linux/linux_common.h
index 97f5a259f300..814c183b338a 100644
--- a/sys/compat/linux/linux_common.h
+++ b/sys/compat/linux/linux_common.h
@@ -43,7 +43,7 @@ sa_family_t bsd_to_linux_domain(sa_family_t domain);
#define AF_UNKNOWN UINT8_MAX
int bsd_to_linux_sockaddr(const struct sockaddr *sa,
struct l_sockaddr **lsa, socklen_t len);
-int linux_to_bsd_sockaddr(const struct l_sockaddr *lsa,
+int linux_to_bsd_sockaddr(struct l_sockaddr *lsa,
struct sockaddr **sap, socklen_t *len);
void linux_to_bsd_poll_events(struct thread *td, int fd,
short lev, short *bev);
diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c
index e88791659f1f..fc3ef7c3e90a 100644
--- a/sys/compat/linux/linux_event.c
+++ b/sys/compat/linux/linux_event.c
@@ -104,7 +104,7 @@ static int
epoll_create_common(struct thread *td, int flags)
{
- return (kern_kqueue(td, flags, NULL));
+ return (kern_kqueue(td, flags, false, NULL));
}
#ifdef LINUX_LEGACY_SYSCALLS
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 0e07b0a60ced..b1a483ce611c 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -2146,7 +2146,8 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
return (ENOPROTOOPT);
}
- if (name == IPV6_NEXTHOP) {
+ switch (name) {
+ case IPV6_NEXTHOP: {
len = args->optlen;
error = linux_to_bsd_sockaddr(PTRIN(args->optval), &sa, &len);
if (error != 0)
@@ -2155,7 +2156,34 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
error = kern_setsockopt(td, args->s, level,
name, sa, UIO_SYSSPACE, len);
free(sa, M_SONAME);
- } else {
+ break;
+ }
+ case MCAST_JOIN_GROUP:
+ case MCAST_LEAVE_GROUP:
+ case MCAST_JOIN_SOURCE_GROUP:
+ case MCAST_LEAVE_SOURCE_GROUP: {
+ struct group_source_req req;
+ size_t size;
+
+ size = (name == MCAST_JOIN_SOURCE_GROUP ||
+ name == MCAST_LEAVE_SOURCE_GROUP) ?
+ sizeof(struct group_source_req) : sizeof(struct group_req);
+
+ if ((error = copyin(PTRIN(args->optval), &req, size)))
+ return (error);
+ len = sizeof(struct sockaddr_storage);
+ if ((error = linux_to_bsd_sockaddr(
+ (struct l_sockaddr *)&req.gsr_group, NULL, &len)))
+ return (error);
+ if (size == sizeof(struct group_source_req) &&
+ (error = linux_to_bsd_sockaddr(
+ (struct l_sockaddr *)&req.gsr_source, NULL, &len)))
+ return (error);
+ error = kern_setsockopt(td, args->s, level, name, &req,
+ UIO_SYSSPACE, size);
+ break;
+ }
+ default:
error = kern_setsockopt(td, args->s, level,
name, PTRIN(args->optval), UIO_USERSPACE, args->optlen);
}
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index 458744a9fec6..ff0f477ea8cc 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -1171,12 +1171,14 @@ static const struct filterops linux_dev_kqfiltops_read = {
.f_isfd = 1,
.f_detach = linux_file_kqfilter_detach,
.f_event = linux_file_kqfilter_read_event,
+ .f_copy = knote_triv_copy,
};
static const struct filterops linux_dev_kqfiltops_write = {
.f_isfd = 1,
.f_detach = linux_file_kqfilter_detach,
.f_event = linux_file_kqfilter_write_event,
+ .f_copy = knote_triv_copy,
};
static void
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index a25ee8f6e1af..9944375c3615 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2801,7 +2801,7 @@ options MAXFILES=999
# Random number generator
# Alternative algorithm.
-#options RANDOM_FENESTRASX
+options RANDOM_FENESTRASX
# Allow the CSPRNG algorithm to be loaded as a module.
#options RANDOM_LOADABLE
# Select this to allow high-rate but potentially expensive
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 856ea3af1372..2f412fa3cb1b 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -73,6 +73,7 @@ arm64/arm64/pmap.c standard
arm64/arm64/ptrace_machdep.c standard
arm64/arm64/sdt_machdep.c optional kdtrace_hooks
arm64/arm64/sigtramp.S standard
+arm64/arm64/spec_workaround.c standard
arm64/arm64/stack_machdep.c optional ddb | stack
arm64/arm64/strcmp.S standard
arm64/arm64/strncmp.S standard
diff --git a/sys/contrib/libnv/bsd_nvpair.c b/sys/contrib/libnv/bsd_nvpair.c
index c73bc2189121..b884dd260b84 100644
--- a/sys/contrib/libnv/bsd_nvpair.c
+++ b/sys/contrib/libnv/bsd_nvpair.c
@@ -985,13 +985,13 @@ nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
size = nvp->nvp_datasize;
tmp = (const char *)ptr;
for (ii = 0; ii < nvp->nvp_nitems; ii++) {
- len = strnlen(tmp, size - 1) + 1;
- size -= len;
- if (tmp[len - 1] != '\0') {
+ if (size <= 0) {
ERRNO_SET(EINVAL);
return (NULL);
}
- if (size < 0) {
+ len = strnlen(tmp, size - 1) + 1;
+ size -= len;
+ if (tmp[len - 1] != '\0') {
ERRNO_SET(EINVAL);
return (NULL);
}
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/sysctl_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/sysctl_os.c
index ace2360c032d..ebc2c0eeb6d2 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/sysctl_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/sysctl_os.c
@@ -163,6 +163,13 @@ param_set_arc_int(SYSCTL_HANDLER_ARGS)
return (0);
}
+static void
+warn_deprecated_sysctl(const char *old, const char *new)
+{
+ printf("WARNING: sysctl vfs.zfs.%s is deprecated. Use vfs.zfs.%s instead.\n",
+ old, new);
+}
+
int
param_set_arc_max(SYSCTL_HANDLER_ARGS)
{
@@ -185,12 +192,15 @@ param_set_arc_max(SYSCTL_HANDLER_ARGS)
if (val != 0)
zfs_arc_max = arc_c_max;
+ if (arg2 != 0)
+ warn_deprecated_sysctl("arc_max", "arc.max");
+
return (0);
}
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max,
CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- NULL, 0, param_set_arc_max, "LU",
+ NULL, 1, param_set_arc_max, "LU",
"Maximum ARC size in bytes (LEGACY)");
int
@@ -214,12 +224,15 @@ param_set_arc_min(SYSCTL_HANDLER_ARGS)
if (val != 0)
zfs_arc_min = arc_c_min;
+ if (arg2 != 0)
+ warn_deprecated_sysctl("arc_min", "arc.min");
+
return (0);
}
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min,
CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- NULL, 0, param_set_arc_min, "LU",
+ NULL, 1, param_set_arc_min, "LU",
"Minimum ARC size in bytes (LEGACY)");
extern uint_t zfs_arc_free_target;
@@ -242,6 +255,9 @@ param_set_arc_free_target(SYSCTL_HANDLER_ARGS)
zfs_arc_free_target = val;
+ if (arg2 != 0)
+ warn_deprecated_sysctl("arc_free_target", "arc.free_target");
+
return (0);
}
@@ -251,7 +267,7 @@ param_set_arc_free_target(SYSCTL_HANDLER_ARGS)
*/
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_free_target,
CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
- NULL, 0, param_set_arc_free_target, "IU",
+ NULL, 1, param_set_arc_free_target, "IU",
"Desired number of free pages below which ARC triggers reclaim"
" (LEGACY)");
@@ -270,12 +286,15 @@ param_set_arc_no_grow_shift(SYSCTL_HANDLER_ARGS)
arc_no_grow_shift = val;
+ if (arg2 != 0)
+ warn_deprecated_sysctl("arc_no_grow_shift", "arc.no_grow_shift");
+
return (0);
}
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_no_grow_shift,
CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- NULL, 0, param_set_arc_no_grow_shift, "I",
+ NULL, 1, param_set_arc_no_grow_shift, "I",
"log2(fraction of ARC which must be free to allow growing) (LEGACY)");
extern uint64_t l2arc_write_max;
@@ -746,12 +765,15 @@ param_set_min_auto_ashift(SYSCTL_HANDLER_ARGS)
zfs_vdev_min_auto_ashift = val;
+ if (arg2 != 0)
+ warn_deprecated_sysctl("min_auto_ashift",
+ "vdev.min_auto_ashift");
+
return (0);
}
SYSCTL_PROC(_vfs_zfs, OID_AUTO, min_auto_ashift,
- CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- &zfs_vdev_min_auto_ashift, sizeof (zfs_vdev_min_auto_ashift),
+ CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, NULL, 1,
param_set_min_auto_ashift, "IU",
"Min ashift used when creating new top-level vdev. (LEGACY)");
@@ -771,12 +793,15 @@ param_set_max_auto_ashift(SYSCTL_HANDLER_ARGS)
zfs_vdev_max_auto_ashift = val;
+ if (arg2 != 0)
+ warn_deprecated_sysctl("max_auto_ashift",
+ "vdev.max_auto_ashift");
+
return (0);
}
SYSCTL_PROC(_vfs_zfs, OID_AUTO, max_auto_ashift,
- CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- &zfs_vdev_max_auto_ashift, sizeof (zfs_vdev_max_auto_ashift),
+ CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, NULL, 1,
param_set_max_auto_ashift, "IU",
"Max ashift used when optimizing for logical -> physical sector size on"
" new top-level vdevs. (LEGACY)");
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
index 0dd2ecd7fd8d..3ddbfcb97184 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
@@ -183,6 +183,7 @@ static struct filterops zvol_filterops_vnode = {
.f_isfd = 1,
.f_detach = zvol_filter_detach,
.f_event = zvol_filter_vnode,
+ .f_copy = knote_triv_copy,
};
extern uint_t zfs_geom_probe_vdev_key;
diff --git a/sys/crypto/chacha20/chacha.c b/sys/crypto/chacha20/chacha.c
index 52f7e18c651c..cb06003b0ecf 100644
--- a/sys/crypto/chacha20/chacha.c
+++ b/sys/crypto/chacha20/chacha.c
@@ -138,7 +138,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
for (;;) {
if (bytes < 64) {
#ifndef KEYSTREAM_ONLY
- for (i = 0;i < bytes;++i) tmp[i] = m[i];
+ for (i = 0; i < bytes; ++i) tmp[i] = m[i];
m = tmp;
#endif
ctarget = c;
@@ -160,7 +160,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
x13 = j13;
x14 = j14;
x15 = j15;
- for (i = 20;i > 0;i -= 2) {
+ for (i = 20; i > 0; i -= 2) {
QUARTERROUND( x0, x4, x8,x12)
QUARTERROUND( x1, x5, x9,x13)
QUARTERROUND( x2, x6,x10,x14)
@@ -240,7 +240,7 @@ chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
if (bytes <= 64) {
if (bytes < 64) {
- for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+ for (i = 0; i < bytes; ++i) ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
diff --git a/sys/crypto/openssl/ossl_sha256.c b/sys/crypto/openssl/ossl_sha256.c
index 4613a9409b44..50cb9739d114 100644
--- a/sys/crypto/openssl/ossl_sha256.c
+++ b/sys/crypto/openssl/ossl_sha256.c
@@ -74,11 +74,11 @@ ossl_sha256_init(void *c_)
unsigned int nn; \
switch ((c)->md_len) \
{ case SHA224_DIGEST_LENGTH: \
- for (nn=0;nn<SHA224_DIGEST_LENGTH/4;nn++) \
+ for (nn=0; nn < SHA224_DIGEST_LENGTH / 4; nn++) \
{ ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \
break; \
case SHA256_DIGEST_LENGTH: \
- for (nn=0;nn<SHA256_DIGEST_LENGTH/4;nn++) \
+ for (nn=0; nn < SHA256_DIGEST_LENGTH / 4; nn++) \
{ ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \
break; \
default: \
diff --git a/sys/dev/ahci/ahciem.c b/sys/dev/ahci/ahciem.c
index c9e6c35f4233..012796aa5d6f 100644
--- a/sys/dev/ahci/ahciem.c
+++ b/sys/dev/ahci/ahciem.c
@@ -479,7 +479,7 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
else
ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
if (ch->disablephy)
- ads->common.bytes[3] |= SESCTL_DEVOFF;
+ ads->bytes[2] |= SESCTL_DEVOFF;
ahci_putch(ch);
}
ccb->ccb_h.status = CAM_REQ_CMP;
diff --git a/sys/dev/aic7xxx/aic79xx.c b/sys/dev/aic7xxx/aic79xx.c
index 2b5015b20e41..cee45fa5cc8a 100644
--- a/sys/dev/aic7xxx/aic79xx.c
+++ b/sys/dev/aic7xxx/aic79xx.c
@@ -7788,8 +7788,8 @@ ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
}
if (role != ROLE_TARGET) {
- for (;i < maxtarget; i++) {
- for (j = minlun;j < maxlun; j++) {
+ for (; i < maxtarget; i++) {
+ for (j = minlun; j < maxlun; j++) {
u_int scbid;
u_int tcl;
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index c09876e9f589..18f68b806948 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -5903,8 +5903,8 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
}
if (role != ROLE_TARGET) {
- for (;i < maxtarget; i++) {
- for (j = minlun;j < maxlun; j++) {
+ for (; i < maxtarget; i++) {
+ for (j = minlun; j < maxlun; j++) {
u_int scbid;
u_int tcl;
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 8563b5f93aa2..137758b104d3 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -5287,6 +5287,7 @@ static const struct filterops psmfiltops = {
.f_isfd = 1,
.f_detach = psmfilter_detach,
.f_event = psmfilter,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/dev/cyapa/cyapa.c b/sys/dev/cyapa/cyapa.c
index ed755f992949..464b03c0ab64 100644
--- a/sys/dev/cyapa/cyapa.c
+++ b/sys/dev/cyapa/cyapa.c
@@ -1121,7 +1121,8 @@ static int cyapafilt(struct knote *, long);
static const struct filterops cyapa_filtops = {
.f_isfd = 1,
.f_detach = cyapafiltdetach,
- .f_event = cyapafilt
+ .f_event = cyapafilt,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index bed74c3b6181..5c1d7ff30976 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -999,7 +999,7 @@ dc_setfilt_21143(struct dc_softc *sc)
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- if_foreach_llmaddr(ifp, dc_hash_maddr_21143, sp);
+ if_foreach_llmaddr(ifp, dc_hash_maddr_21143, sc);
if (if_getflags(ifp) & IFF_BROADCAST) {
h = dc_mchash_le(sc, if_getbroadcastaddr(ifp));
diff --git a/sys/dev/enetc/if_enetc.c b/sys/dev/enetc/if_enetc.c
index 808397b229a7..53002f9d73ce 100644
--- a/sys/dev/enetc/if_enetc.c
+++ b/sys/dev/enetc/if_enetc.c
@@ -848,7 +848,7 @@ enetc_hash_vid(uint16_t vid)
bool bit;
int i;
- for (i = 0;i < 6;i++) {
+ for (i = 0; i < 6; i++) {
bit = vid & BIT(i);
bit ^= !!(vid & BIT(i + 6));
hash |= bit << i;
@@ -1020,7 +1020,7 @@ enetc_msix_intr_assign(if_ctx_t ctx, int msix)
ENETC_RBICR0_ICEN | ENETC_RBICR0_SET_ICPT(ENETC_RX_INTR_PKT_THR));
}
vector = 0;
- for (i = 0;i < sc->tx_num_queues; i++, vector++) {
+ for (i = 0; i < sc->tx_num_queues; i++, vector++) {
tx_queue = &sc->tx_queues[i];
snprintf(irq_name, sizeof(irq_name), "txq%d", i);
iflib_softirq_alloc_generic(ctx, &tx_queue->irq,
@@ -1130,7 +1130,7 @@ enetc_isc_txd_encap(void *data, if_pkt_info_t ipi)
}
/* Now add remaining descriptors. */
- for (;i < ipi->ipi_nsegs; i++) {
+ for (; i < ipi->ipi_nsegs; i++) {
desc = &queue->ring[pidx];
bzero(desc, sizeof(*desc));
desc->addr = segs[i].ds_addr;
diff --git a/sys/dev/evdev/cdev.c b/sys/dev/evdev/cdev.c
index 9fe1299a0937..dd4115cdfc71 100644
--- a/sys/dev/evdev/cdev.c
+++ b/sys/dev/evdev/cdev.c
@@ -96,6 +96,7 @@ static const struct filterops evdev_cdev_filterops = {
.f_attach = NULL,
.f_detach = evdev_kqdetach,
.f_event = evdev_kqread,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/dev/evdev/uinput.c b/sys/dev/evdev/uinput.c
index 9ac9fee8a157..76a530479c02 100644
--- a/sys/dev/evdev/uinput.c
+++ b/sys/dev/evdev/uinput.c
@@ -104,6 +104,7 @@ static const struct filterops uinput_filterops = {
.f_attach = NULL,
.f_detach = uinput_kqdetach,
.f_event = uinput_kqread,
+ .f_copy = knote_triv_copy,
};
struct uinput_cdev_state
diff --git a/sys/dev/gpio/gpioc.c b/sys/dev/gpio/gpioc.c
index 6c6f79227166..517f7752daad 100644
--- a/sys/dev/gpio/gpioc.c
+++ b/sys/dev/gpio/gpioc.c
@@ -158,7 +158,8 @@ static const struct filterops gpioc_read_filterops = {
.f_attach = NULL,
.f_detach = gpioc_kqdetach,
.f_event = gpioc_kqread,
- .f_touch = NULL
+ .f_touch = NULL,
+ .f_copy = knote_triv_copy,
};
static struct gpioc_pin_event *
diff --git a/sys/dev/hid/hidraw.c b/sys/dev/hid/hidraw.c
index 4855843cd265..5b5e9b58f8bd 100644
--- a/sys/dev/hid/hidraw.c
+++ b/sys/dev/hid/hidraw.c
@@ -182,6 +182,7 @@ static const struct filterops hidraw_filterops_read = {
.f_isfd = 1,
.f_detach = hidraw_kqdetach,
.f_event = hidraw_kqread,
+ .f_copy = knote_triv_copy,
};
static void
diff --git a/sys/dev/hid/u2f.c b/sys/dev/hid/u2f.c
index 08f1a5ceedba..e1f696d72f01 100644
--- a/sys/dev/hid/u2f.c
+++ b/sys/dev/hid/u2f.c
@@ -132,6 +132,7 @@ static struct filterops u2f_filterops_read = {
.f_isfd = 1,
.f_detach = u2f_kqdetach,
.f_event = u2f_kqread,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c
index 5c4718bf582f..f3d58f285b39 100644
--- a/sys/dev/hptmv/entry.c
+++ b/sys/dev/hptmv/entry.c
@@ -430,7 +430,7 @@ static void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plug
if(pVDev->pParent)
{
int iMember;
- for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++)
+ for (iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++)
if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev)
pVDev->pParent->u.array.pMember[iMember] = NULL;
pVDev->pParent = NULL;
@@ -984,7 +984,7 @@ fRegisterVdevice(IAL_ADAPTER_T *pAdapter)
PVBus pVBus;
int i,j;
- for(i=0;i<MV_SATA_CHANNELS_NUM;i++) {
+ for (i = 0; i < MV_SATA_CHANNELS_NUM; i++) {
pPhysical = &(pAdapter->VDevices[i]);
pLogical = pPhysical;
while (pLogical->pParent) pLogical = pLogical->pParent;
@@ -1027,8 +1027,7 @@ GetSpareDisk(_VBUS_ARG PVDevice pArray)
PVDevice pVDevice, pFind = NULL;
int i;
- for(i=0;i<MV_SATA_CHANNELS_NUM;i++)
- {
+ for (i=0; i < MV_SATA_CHANNELS_NUM; i++) {
pVDevice = &pAdapter->VDevices[i];
if(!pVDevice)
continue;
@@ -1356,7 +1355,7 @@ unregister:
goto unregister;
}
- for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) {
+ for (i = 0; i < MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) {
FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i]));
}
@@ -1370,7 +1369,7 @@ unregister:
memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM);
pAdapter->pbus_dmamap_list = 0;
- for (i=0; i < MAX_QUEUE_COMM; i++) {
+ for (i = 0; i < MAX_QUEUE_COMM; i++) {
PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]);
pmap->pAdapter = pAdapter;
dmamap_put(pmap);
@@ -1398,7 +1397,7 @@ unregister:
pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL);
{
PUCHAR PRDTable = pAdapter->prdTableAlignedAddr;
- for (i=0; i<PRD_TABLES_FOR_VBUS; i++)
+ for (i = 0; i < PRD_TABLES_FOR_VBUS; i++)
{
/* KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */
FreePRDTable(pAdapter, PRDTable);
@@ -1447,7 +1446,7 @@ unregister:
}
#ifdef SUPPORT_ARRAY
- for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) {
+ for (i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) {
pVDev = ArrayTables(i);
mArFreeArrayTable(pVDev);
}
@@ -1467,7 +1466,7 @@ unregister:
_vbus_p->nInstances = 1;
fRegisterVdevice(pAdapter);
- for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) {
+ for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
pVDev = _vbus_p->pVDevice[channel];
if (pVDev && pVDev->vf_online)
fCheckBootable(pVDev);
@@ -1567,7 +1566,7 @@ fResetActiveCommands(PVBus _vbus_p)
{
MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
MV_U8 channel;
- for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
+ for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands)
MvSataResetChannel(pMvSataAdapter,channel);
}
@@ -1590,7 +1589,7 @@ check_cmds:
dataxfer_poll();
xor_poll();
#endif
- for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
+ for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
pMvSataChannel = pMvSataAdapter->sataChannel[channel];
if (pMvSataChannel && pMvSataChannel->outstandingCommands)
{
@@ -1716,7 +1715,7 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd)
MV_BOOLEAN is48bit;
MV_U8 channel;
- int i=0;
+ int i = 0;
DECLARE_BUFFER(FPSCAT_GATH, tmpSg);
@@ -2141,7 +2140,7 @@ FlushAdapter(IAL_ADAPTER_T *pAdapter)
hpt_printk(("flush all devices\n"));
/* flush all devices */
- for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) {
+ for (i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
PVDevice pVDev = pAdapter->VBus.pVDevice[i];
if(pVDev) fFlushVDev(pVDev);
}
@@ -2174,7 +2173,7 @@ Check_Idle_Call(IAL_ADAPTER_T *pAdapter)
{
int i;
PVDevice pArray;
- for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){
+ for (i = 0; i < MAX_ARRAY_PER_VBUS; i++) {
if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
continue;
else if (pArray->u.array.rf_auto_rebuild) {
@@ -2378,7 +2377,7 @@ hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb)
static void hpt_worker_thread(void)
{
- for(;;) {
+ for (;;) {
mtx_lock(&DpcQueue_Lock);
while (DpcQueue_First!=DpcQueue_Last) {
ST_HPT_DPC p;
@@ -2418,7 +2417,7 @@ static void hpt_worker_thread(void)
mtx_lock(&pAdapter->lock);
_vbus_p = &pAdapter->VBus;
- for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
+ for (i = 0; i < MAX_ARRAY_PER_VBUS; i++)
{
if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
continue;
@@ -2472,7 +2471,7 @@ launch_worker_thread(void)
int i;
PVDevice pVDev;
- for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
+ for (i = 0; i < MAX_ARRAY_PER_VBUS; i++)
if ((pVDev=ArrayTables(i))->u.array.dArStamp==0)
continue;
else{
diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c
index d78fdcca69d2..f11044db733a 100644
--- a/sys/dev/hptmv/gui_lib.c
+++ b/sys/dev/hptmv/gui_lib.c
@@ -86,8 +86,7 @@ check_VDevice_valid(PVDevice p)
while(pAdapter != NULL)
{
_vbus_p = &pAdapter->VBus;
- for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
- {
+ for (i = 0; i<MAX_ARRAY_PER_VBUS; i++) {
pVDevice=ArrayTables(i);
if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
return 0;
@@ -244,9 +243,9 @@ static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo)
if(pVDevice->u.array.pMember[i] != NULL)
pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
- for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS; i++)
+ for (i = pArrayInfo->nDisk; i < MAX_ARRAY_MEMBERS; i++)
pArrayInfo->Members[i] = INVALID_DEVICEID;
- }
+}
static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
{
@@ -266,7 +265,7 @@ static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
if(pVDevice->u.array.pMember[i] != NULL)
pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
- for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS_V2; i++)
+ for (i = pArrayInfo->nDisk; i < MAX_ARRAY_MEMBERS_V2; i++)
pArrayInfo->Members[i] = INVALID_DEVICEID;
}
#endif
@@ -461,8 +460,7 @@ found:
pInfo->IoPort = 0;
pInfo->ControlPort = 0;
- for (i=0; i<2 ;i++)
- {
+ for (i = 0; i < 2; i++) {
pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
}
diff --git a/sys/dev/hptmv/hptproc.c b/sys/dev/hptmv/hptproc.c
index 38fe61ee7e04..328750d9034c 100644
--- a/sys/dev/hptmv/hptproc.c
+++ b/sys/dev/hptmv/hptproc.c
@@ -107,7 +107,7 @@ hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length)
return -EINVAL;
}
- for (i=0;i<MV_SATA_CHANNELS_NUM;i++)
+ for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
if(i == ichan)
goto rebuild;
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index 261f76055901..bfaf6cd69e58 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -1480,17 +1480,33 @@ ixl_if_multi_set(if_ctx_t ctx)
struct ixl_pf *pf = iflib_get_softc(ctx);
struct ixl_vsi *vsi = &pf->vsi;
struct i40e_hw *hw = vsi->hw;
+ enum i40e_status_code status;
int mcnt;
+ if_t ifp = iflib_get_ifp(ctx);
IOCTL_DEBUGOUT("ixl_if_multi_set: begin");
/* Delete filters for removed multicast addresses */
ixl_del_multi(vsi, false);
- mcnt = min(if_llmaddr_count(iflib_get_ifp(ctx)), MAX_MULTICAST_ADDR);
+ mcnt = min(if_llmaddr_count(ifp), MAX_MULTICAST_ADDR);
if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) {
- i40e_aq_set_vsi_multicast_promiscuous(hw,
+ /* Check if promisc mode is already enabled, if yes return */
+ if (vsi->flags & IXL_FLAGS_MC_PROMISC)
+ return;
+
+ status = i40e_aq_set_vsi_multicast_promiscuous(hw,
vsi->seid, TRUE, NULL);
+ if (status != I40E_SUCCESS)
+ if_printf(ifp, "Failed to enable multicast promiscuous "
+ "mode, status: %s\n", i40e_stat_str(hw, status));
+ else {
+ if_printf(ifp, "Enabled multicast promiscuous mode\n");
+
+ /* Set the flag to track promiscuous mode */
+ vsi->flags |= IXL_FLAGS_MC_PROMISC;
+ }
+ /* Delete all existing MC filters */
ixl_del_multi(vsi, true);
return;
}
@@ -1693,6 +1709,13 @@ ixl_if_promisc_set(if_ctx_t ctx, int flags)
return (err);
err = i40e_aq_set_vsi_multicast_promiscuous(hw,
vsi->seid, multi, NULL);
+
+ /* Update the multicast promiscuous flag based on the new state */
+ if (multi)
+ vsi->flags |= IXL_FLAGS_MC_PROMISC;
+ else
+ vsi->flags &= ~IXL_FLAGS_MC_PROMISC;
+
return (err);
}
diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h
index 95379448b570..ab0f38307d90 100644
--- a/sys/dev/ixl/ixl.h
+++ b/sys/dev/ixl/ixl.h
@@ -202,6 +202,7 @@
#define IXL_FLAGS_KEEP_TSO6 (1 << 1)
#define IXL_FLAGS_USES_MSIX (1 << 2)
#define IXL_FLAGS_IS_VF (1 << 3)
+#define IXL_FLAGS_MC_PROMISC (1 << 4)
#define IXL_VSI_IS_PF(v) ((v->flags & IXL_FLAGS_IS_VF) == 0)
#define IXL_VSI_IS_VF(v) ((v->flags & IXL_FLAGS_IS_VF) != 0)
diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c
index 1752efc02fff..b62619ced5cb 100644
--- a/sys/dev/ixl/ixl_pf_main.c
+++ b/sys/dev/ixl/ixl_pf_main.c
@@ -593,24 +593,29 @@ ixl_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
* Routines for multicast and vlan filter management.
*
*********************************************************************/
+
+/**
+ * ixl_add_multi - Add multicast filters to the hardware
+ * @vsi: The VSI structure
+ *
+ * In case number of multicast filters in the IFP exceeds 127 entries,
+ * multicast promiscuous mode will be enabled and the filters will be removed
+ * from the hardware
+ */
void
ixl_add_multi(struct ixl_vsi *vsi)
{
if_t ifp = vsi->ifp;
- struct i40e_hw *hw = vsi->hw;
int mcnt = 0;
struct ixl_add_maddr_arg cb_arg;
IOCTL_DEBUGOUT("ixl_add_multi: begin");
- mcnt = if_llmaddr_count(ifp);
- if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
- i40e_aq_set_vsi_multicast_promiscuous(hw,
- vsi->seid, TRUE, NULL);
- /* delete all existing MC filters */
- ixl_del_multi(vsi, true);
- return;
- }
+ /*
+ * There is no need to check if the number of multicast addresses
+ * exceeds the MAX_MULTICAST_ADDR threshold and set promiscuous mode
+ * here, as all callers already handle this case.
+ */
cb_arg.vsi = vsi;
LIST_INIT(&cb_arg.to_add);
@@ -633,30 +638,103 @@ ixl_match_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
return (0);
}
+/**
+ * ixl_dis_multi_promisc - Disable multicast promiscuous mode
+ * @vsi: The VSI structure
+ * @vsi_mcnt: Number of multicast filters in the VSI
+ *
+ * Disable multicast promiscuous mode based on number of entries in the IFP
+ * and the VSI, then re-add multicast filters.
+ *
+ */
+static void
+ixl_dis_multi_promisc(struct ixl_vsi *vsi, int vsi_mcnt)
+{
+ struct ifnet *ifp = vsi->ifp;
+ struct i40e_hw *hw = vsi->hw;
+ int ifp_mcnt = 0;
+ enum i40e_status_code status;
+
+ /*
+ * Check if multicast promiscuous mode was actually enabled.
+ * If promiscuous mode was not enabled, don't attempt to disable it.
+ * Also, don't disable if IFF_PROMISC or IFF_ALLMULTI is set.
+ */
+ if (!(vsi->flags & IXL_FLAGS_MC_PROMISC) ||
+ (if_getflags(ifp) & (IFF_PROMISC | IFF_ALLMULTI)))
+ return;
+
+ ifp_mcnt = if_llmaddr_count(ifp);
+ /*
+ * Equal lists or empty ifp list mean the list has not been changed
+ * and in such case avoid disabling multicast promiscuous mode as it
+ * was not previously enabled. Case where multicast promiscuous mode has
+ * been enabled is when vsi_mcnt == 0 && ifp_mcnt > 0.
+ */
+ if (ifp_mcnt == vsi_mcnt || ifp_mcnt == 0 ||
+ ifp_mcnt >= MAX_MULTICAST_ADDR)
+ return;
+
+ status = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
+ FALSE, NULL);
+ if (status != I40E_SUCCESS) {
+ if_printf(ifp, "Failed to disable multicast promiscuous "
+ "mode, status: %s\n", i40e_stat_str(hw, status));
+
+ return;
+ }
+
+ /* Clear the flag since promiscuous mode is now disabled */
+ vsi->flags &= ~IXL_FLAGS_MC_PROMISC;
+ if_printf(ifp, "Disabled multicast promiscuous mode\n");
+
+ ixl_add_multi(vsi);
+}
+
+/**
+ * ixl_del_multi - Delete multicast filters from the hardware
+ * @vsi: The VSI structure
+ * @all: Bool to determine if all the multicast filters should be removed
+ *
+ * In case number of multicast filters in the IFP drops to 127 entries,
+ * multicast promiscuous mode will be disabled and the filters will be reapplied
+ * to the hardware.
+ */
void
ixl_del_multi(struct ixl_vsi *vsi, bool all)
{
- struct ixl_ftl_head to_del;
+ int to_del_cnt = 0, vsi_mcnt = 0;
if_t ifp = vsi->ifp;
struct ixl_mac_filter *f, *fn;
- int mcnt = 0;
+ struct ixl_ftl_head to_del;
IOCTL_DEBUGOUT("ixl_del_multi: begin");
LIST_INIT(&to_del);
/* Search for removed multicast addresses */
LIST_FOREACH_SAFE(f, &vsi->ftl, ftle, fn) {
- if ((f->flags & IXL_FILTER_MC) == 0 ||
- (!all && (if_foreach_llmaddr(ifp, ixl_match_maddr, f) == 0)))
+ if ((f->flags & IXL_FILTER_MC) == 0)
+ continue;
+
+ /* Count all the multicast filters in the VSI for comparison */
+ vsi_mcnt++;
+
+ if (!all && if_foreach_llmaddr(ifp, ixl_match_maddr, f) != 0)
continue;
LIST_REMOVE(f, ftle);
LIST_INSERT_HEAD(&to_del, f, ftle);
- mcnt++;
+ to_del_cnt++;
}
- if (mcnt > 0)
- ixl_del_hw_filters(vsi, &to_del, mcnt);
+ if (to_del_cnt > 0) {
+ ixl_del_hw_filters(vsi, &to_del, to_del_cnt);
+ return;
+ }
+
+ ixl_dis_multi_promisc(vsi, vsi_mcnt);
+
+ IOCTL_DEBUGOUT("ixl_del_multi: end");
}
void
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index d69c8ea5fded..fa0f817ed67b 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -858,7 +858,7 @@ mps_detach_sas(struct mps_softc *sc)
if (sassc->devq != NULL)
cam_simq_free(sassc->devq);
- for(i=0; i< sassc->maxtargets ;i++) {
+ for (i = 0; i < sassc->maxtargets; i++) {
targ = &sassc->targets[i];
SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
free(lun, M_MPT2);
@@ -3396,7 +3396,7 @@ mpssas_realloc_targets(struct mps_softc *sc, int maxtargets)
* the allocated LUNs for each target and then the target buffer
* itself.
*/
- for (i=0; i< maxtargets; i++) {
+ for (i = 0; i < maxtargets; i++) {
targ = &sassc->targets[i];
SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
free(lun, M_MPT2);
diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c
index 5ff08ffcf2b3..2b868f6ef070 100644
--- a/sys/dev/mpt/mpt_raid.c
+++ b/sys/dev/mpt/mpt_raid.c
@@ -830,7 +830,7 @@ mpt_is_raid_volume(struct mpt_softc *mpt, target_id_t tgt)
}
ioc_vol = mpt->ioc_page2->RaidVolume;
ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
- for (;ioc_vol != ioc_last_vol; ioc_vol++) {
+ for (; ioc_vol != ioc_last_vol; ioc_vol++) {
if (ioc_vol->VolumeID == tgt) {
return (1);
}
@@ -1406,7 +1406,7 @@ mpt_refresh_raid_data(struct mpt_softc *mpt)
ioc_vol = mpt->ioc_page2->RaidVolume;
ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
- for (;ioc_vol != ioc_last_vol; ioc_vol++) {
+ for (; ioc_vol != ioc_last_vol; ioc_vol++) {
struct mpt_raid_volume *mpt_vol;
mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber;
diff --git a/sys/dev/netmap/netmap_freebsd.c b/sys/dev/netmap/netmap_freebsd.c
index 8cc543d54c2e..9fb4370129f3 100644
--- a/sys/dev/netmap/netmap_freebsd.c
+++ b/sys/dev/netmap/netmap_freebsd.c
@@ -738,6 +738,7 @@ nm_os_extmem_create(unsigned long p, struct nmreq_pools_info *pi, int *perror)
out_rem:
vm_map_remove(kernel_map, e->kva, e->kva + e->size);
+ e->obj = NULL; /* reference consumed by vm_map_remove() */
out_rel:
vm_object_deallocate(e->obj);
e->obj = NULL;
@@ -1406,19 +1407,34 @@ netmap_knwrite(struct knote *kn, long hint)
return netmap_knrw(kn, hint, POLLOUT);
}
+static int
+netmap_kncopy(struct knote *kn, struct proc *p1)
+{
+ struct netmap_priv_d *priv;
+ struct nm_selinfo *si;
+
+ priv = kn->kn_hook;
+ si = priv->np_si[kn->kn_filter == EVFILT_WRITE ? NR_TX : NR_RX];
+ NMG_LOCK();
+ si->kqueue_users++;
+ NMG_UNLOCK();
+ return (0);
+}
+
static const struct filterops netmap_rfiltops = {
.f_isfd = 1,
.f_detach = netmap_knrdetach,
.f_event = netmap_knread,
+ .f_copy = netmap_kncopy,
};
static const struct filterops netmap_wfiltops = {
.f_isfd = 1,
.f_detach = netmap_knwdetach,
.f_event = netmap_knwrite,
+ .f_copy = netmap_kncopy,
};
-
/*
* This is called when a thread invokes kevent() to record
* a change in the configuration of the kqueue().
diff --git a/sys/dev/nfe/if_nfe.c b/sys/dev/nfe/if_nfe.c
index 4625c2616562..265181ef7ad0 100644
--- a/sys/dev/nfe/if_nfe.c
+++ b/sys/dev/nfe/if_nfe.c
@@ -2078,7 +2078,7 @@ nfe_rxeof(struct nfe_softc *sc, int count, int *rx_npktsp)
bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map,
BUS_DMASYNC_POSTREAD);
- for (prog = 0;;NFE_INC(sc->rxq.cur, NFE_RX_RING_COUNT), vtag = 0) {
+ for (prog = 0; ; NFE_INC(sc->rxq.cur, NFE_RX_RING_COUNT), vtag = 0) {
if (count <= 0)
break;
count--;
@@ -2192,7 +2192,7 @@ nfe_jrxeof(struct nfe_softc *sc, int count, int *rx_npktsp)
bus_dmamap_sync(sc->jrxq.jrx_desc_tag, sc->jrxq.jrx_desc_map,
BUS_DMASYNC_POSTREAD);
- for (prog = 0;;NFE_INC(sc->jrxq.jcur, NFE_JUMBO_RX_RING_COUNT),
+ for (prog = 0; ; NFE_INC(sc->jrxq.jcur, NFE_JUMBO_RX_RING_COUNT),
vtag = 0) {
if (count <= 0)
break;
diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c
index 8525eb9543c3..b5725de30bef 100644
--- a/sys/dev/null/null.c
+++ b/sys/dev/null/null.c
@@ -61,12 +61,14 @@ static int zero_ev(struct knote *kn, long hint);
static const struct filterops one_fop = {
.f_isfd = 1,
- .f_event = one_ev
+ .f_event = one_ev,
+ .f_copy = knote_triv_copy,
};
static const struct filterops zero_fop = {
.f_isfd = 1,
- .f_event = zero_ev
+ .f_event = zero_ev,
+ .f_copy = knote_triv_copy,
};
static struct cdevsw full_cdevsw = {
diff --git a/sys/dev/ocs_fc/ocs_mgmt.c b/sys/dev/ocs_fc/ocs_mgmt.c
index 726b499f28ba..5b7f6557c017 100644
--- a/sys/dev/ocs_fc/ocs_mgmt.c
+++ b/sys/dev/ocs_fc/ocs_mgmt.c
@@ -226,7 +226,7 @@ ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
- for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
+ for (i = 0; i < ARRAY_SIZE(mgmt_table); i++) {
access = 0;
if (mgmt_table[i].get_handler) {
access |= MGMT_MODE_RD;
@@ -305,7 +305,7 @@ ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
char *unqualified_name = name + strlen(qualifier) + 1;
- for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
+ for (i = 0; i < ARRAY_SIZE(mgmt_table); i++) {
if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
if (mgmt_table[i].get_handler) {
mgmt_table[i].get_handler(ocs, name, textbuf);
@@ -387,7 +387,7 @@ ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
char *unqualified_name = name + strlen(qualifier) +1;
/* See if it's a value I can set */
- for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
+ for (i = 0; i < ARRAY_SIZE(mgmt_table); i++) {
if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
if (mgmt_table[i].set_handler) {
return mgmt_table[i].set_handler(ocs, name, value);
@@ -469,7 +469,7 @@ ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in,
char *unqualified_name = action + strlen(qualifier) +1;
/* See if it's an action I can perform */
- for (i=0;i<ARRAY_SIZE(mgmt_table); i++) {
+ for (i = 0; i < ARRAY_SIZE(mgmt_table); i++) {
if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
if (mgmt_table[i].action_handler) {
return mgmt_table[i].action_handler(ocs, action, arg_in, arg_in_length,
@@ -527,7 +527,7 @@ ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
- for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
+ for (i = 0; i < ARRAY_SIZE(mgmt_table); i++) {
if (mgmt_table[i].get_handler) {
mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf);
} else if (mgmt_table[i].action_handler) {
@@ -1212,7 +1212,7 @@ get_sfp_a2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1;
int bytes_added;
- for (i=0; i < bytes_read; i++) {
+ for (i = 0; i < bytes_read; i++) {
bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s);
++s;
d += bytes_added;
@@ -2040,7 +2040,7 @@ get_profile_list(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
result_buf = ocs_malloc(ocs, BUFFER_SIZE, OCS_M_ZERO);
bytes_left = BUFFER_SIZE;
- for (i=0; i<result.list->num_descriptors; i++) {
+ for (i = 0; i < result.list->num_descriptors; i++) {
sprintf(result_line, "0x%02x:%s\n", result.list->descriptors[i].profile_id,
result.list->descriptors[i].profile_description);
if (strlen(result_line) < bytes_left) {
diff --git a/sys/dev/pci/controller/pci_n1sdp.c b/sys/dev/pci/controller/pci_n1sdp.c
index 487041bc78e4..22f0ea27d45b 100644
--- a/sys/dev/pci/controller/pci_n1sdp.c
+++ b/sys/dev/pci/controller/pci_n1sdp.c
@@ -345,6 +345,17 @@ n1sdp_pcie_write_config(device_t dev, u_int bus, u_int slot,
bus_space_write_4(t, h, offset & ~3, data);
}
+static int
+n1sdp_pcie_acpi_request_feature(device_t pcib __unused, device_t dev __unused,
+ enum pci_feature feature __unused)
+{
+ /*
+ * HotPlug isn't supported on the N1SDP as it causes an interrupt storm
+ */
+ return (EINVAL);
+}
+
+
static device_method_t n1sdp_pcie_acpi_methods[] = {
DEVMETHOD(device_probe, n1sdp_pcie_acpi_probe),
DEVMETHOD(device_attach, n1sdp_pcie_acpi_attach),
@@ -352,6 +363,7 @@ static device_method_t n1sdp_pcie_acpi_methods[] = {
/* pcib interface */
DEVMETHOD(pcib_read_config, n1sdp_pcie_read_config),
DEVMETHOD(pcib_write_config, n1sdp_pcie_write_config),
+ DEVMETHOD(pcib_request_feature, n1sdp_pcie_acpi_request_feature),
DEVMETHOD_END
};
diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c
index 9870379e2eba..de75f4747709 100644
--- a/sys/dev/ppc/ppc.c
+++ b/sys/dev/ppc/ppc.c
@@ -1389,7 +1389,7 @@ ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
/* let's suppose the next instr. is the same */
prefetch:
- for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
+ for (; mi->opcode == MS_OP_RASSERT; INCR_PC)
w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i);
if (mi->opcode == MS_OP_DELAY) {
diff --git a/sys/dev/qat/qat_common/adf_freebsd_dev_processes.c b/sys/dev/qat/qat_common/adf_freebsd_dev_processes.c
index 67e1d4ad2cab..c5b745bb78fb 100644
--- a/sys/dev/qat/qat_common/adf_freebsd_dev_processes.c
+++ b/sys/dev/qat/qat_common/adf_freebsd_dev_processes.c
@@ -89,6 +89,7 @@ static struct filterops adf_state_read_filterops = {
.f_attach = NULL,
.f_detach = adf_state_kqread_detach,
.f_event = adf_state_kqread_event,
+ .f_copy = knote_triv_copy,
};
static struct cdev *adf_processes_dev;
diff --git a/sys/dev/smartpqi/smartpqi_event.c b/sys/dev/smartpqi/smartpqi_event.c
index f000d9ce9db3..88dcf45dd08a 100644
--- a/sys/dev/smartpqi/smartpqi_event.c
+++ b/sys/dev/smartpqi/smartpqi_event.c
@@ -115,7 +115,7 @@ pqisrc_ack_all_events(void *arg1)
pending_event = &softs->pending_events[0];
- for (i=0; i < PQI_NUM_SUPPORTED_EVENTS; i++) {
+ for (i = 0; i < PQI_NUM_SUPPORTED_EVENTS; i++) {
if (pending_event->pending == true) {
pending_event->pending = false;
pqisrc_acknowledge_event(softs, pending_event);
@@ -417,7 +417,7 @@ pqisrc_report_event_config(pqisrc_softstate_t *softs)
softs->event_config.num_event_descriptors = MIN(event_config_p->num_event_descriptors,
PQI_MAX_EVENT_DESCRIPTORS) ;
- for (i=0; i < softs->event_config.num_event_descriptors ;i++){
+ for (i = 0; i < softs->event_config.num_event_descriptors; i++) {
softs->event_config.descriptors[i].event_type =
event_config_p->descriptors[i].event_type;
}
@@ -477,7 +477,7 @@ pqisrc_set_event_config(pqisrc_softstate_t *softs)
event_config_p->num_event_descriptors = softs->event_config.num_event_descriptors;
- for (i=0; i < softs->event_config.num_event_descriptors ; i++){
+ for (i = 0; i < softs->event_config.num_event_descriptors; i++) {
event_config_p->descriptors[i].event_type =
softs->event_config.descriptors[i].event_type;
if( pqisrc_event_type_to_event_index(event_config_p->descriptors[i].event_type) != -1)
diff --git a/sys/dev/smartpqi/smartpqi_queue.c b/sys/dev/smartpqi/smartpqi_queue.c
index 2e80b01b5436..f05c951cd4f9 100644
--- a/sys/dev/smartpqi/smartpqi_queue.c
+++ b/sys/dev/smartpqi/smartpqi_queue.c
@@ -700,7 +700,7 @@ pqisrc_create_op_obq(pqisrc_softstate_t *softs,
} else {
int i = 0;
DBG_WARN("Error Status Descriptors\n");
- for(i = 0; i < 4;i++)
+ for (i = 0; i < 4; i++)
DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]);
}
@@ -743,7 +743,7 @@ pqisrc_create_op_ibq(pqisrc_softstate_t *softs,
} else {
int i = 0;
DBG_WARN("Error Status Decsriptors\n");
- for(i = 0; i < 4;i++)
+ for (i = 0; i < 4; i++)
DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]);
}
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index fa65d544e17d..b4e5c1075fb4 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -3266,7 +3266,7 @@ static void sym_init (hcb_p np, int reason)
* Reinitialize usrwide.
* Prepare sync negotiation according to actual SCSI bus mode.
*/
- for (i=0;i<SYM_CONF_MAX_TARGET;i++) {
+ for (i = 0; i < SYM_CONF_MAX_TARGET; i++) {
tcb_p tp = &np->target[i];
tp->to_reset = 0;
@@ -3715,7 +3715,7 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
}
printf ("%s: regdump:", sym_name(np));
- for (i=0; i<24;i++)
+ for (i = 0; i < 24; i++)
printf (" %02x", (unsigned)INB_OFF(i));
printf (".\n");
@@ -5527,8 +5527,8 @@ static int sym_show_msg (u_char * msg)
u_char i;
printf ("%x",*msg);
if (*msg==M_EXTENDED) {
- for (i=1;i<8;i++) {
- if (i-1>msg[1]) break;
+ for (i = 1; i < 8; i++) {
+ if (i - 1 > msg[1]) break;
printf ("-%x",msg[i]);
}
return (i+1);
@@ -6744,10 +6744,10 @@ restart_test:
/*
* Wait 'til done (with timeout)
*/
- for (i=0; i<SYM_SNOOP_TIMEOUT; i++)
+ for (i = 0; i < SYM_SNOOP_TIMEOUT; i++)
if (INB(nc_istat) & (INTF|SIP|DIP))
break;
- if (i>=SYM_SNOOP_TIMEOUT) {
+ if (i >= SYM_SNOOP_TIMEOUT) {
printf ("CACHE TEST FAILED: timeout.\n");
return (0x20);
}
diff --git a/sys/dev/tws/tws.c b/sys/dev/tws/tws.c
index af151c8c4f06..fccd6689a6aa 100644
--- a/sys/dev/tws/tws.c
+++ b/sys/dev/tws/tws.c
@@ -311,7 +311,7 @@ attach_fail_4:
if (sc->cmd_tag)
bus_dma_tag_destroy(sc->cmd_tag);
attach_fail_3:
- for(i=0;i<sc->irqs;i++) {
+ for (i = 0; i < sc->irqs; i++) {
if ( sc->irq_res[i] ){
if (bus_release_resource(sc->tws_dev,
SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
@@ -369,7 +369,7 @@ tws_detach(device_t dev)
tws_teardown_intr(sc);
/* Release irq resource */
- for(i=0;i<sc->irqs;i++) {
+ for (i = 0; i < sc->irqs; i++) {
if ( sc->irq_res[i] ){
if (bus_release_resource(sc->tws_dev,
SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
@@ -402,7 +402,7 @@ tws_detach(device_t dev)
TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id);
}
- for ( i=0; i< tws_queue_depth; i++) {
+ for (i = 0; i < tws_queue_depth; i++) {
if (sc->reqs[i].dma_map)
bus_dmamap_destroy(sc->data_tag, sc->reqs[i].dma_map);
callout_drain(&sc->reqs[i].timeout);
@@ -432,7 +432,7 @@ tws_setup_intr(struct tws_softc *sc, int irqs)
{
int i, error;
- for(i=0;i<irqs;i++) {
+ for (i = 0; i < irqs; i++) {
if (!(sc->intr_handle[i])) {
if ((error = bus_setup_intr(sc->tws_dev, sc->irq_res[i],
INTR_TYPE_CAM | INTR_MPSAFE,
@@ -452,7 +452,7 @@ tws_teardown_intr(struct tws_softc *sc)
{
int i;
- for(i=0;i<sc->irqs;i++) {
+ for (i = 0; i < sc->irqs; i++) {
if (sc->intr_handle[i]) {
bus_teardown_intr(sc->tws_dev,
sc->irq_res[i], sc->intr_handle[i]);
@@ -669,8 +669,7 @@ tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size)
bzero(cmd_buf, dma_mem_size);
TWS_TRACE_DEBUG(sc, "phy cmd", sc->dma_mem_phys, 0);
mtx_lock(&sc->q_lock);
- for ( i=0; i< tws_queue_depth; i++)
- {
+ for (i = 0; i < tws_queue_depth; i++) {
if (bus_dmamap_create(sc->data_tag, 0, &sc->reqs[i].dma_map)) {
/* log a ENOMEM failure msg here */
mtx_unlock(&sc->q_lock);
diff --git a/sys/dev/tws/tws_services.c b/sys/dev/tws/tws_services.c
index da8bbacc39f7..e5c3d45c533f 100644
--- a/sys/dev/tws/tws_services.c
+++ b/sys/dev/tws/tws_services.c
@@ -200,7 +200,7 @@ tws_init_qs(struct tws_softc *sc)
{
mtx_lock(&sc->q_lock);
- for(int i=0;i<TWS_MAX_QS;i++) {
+ for (int i = 0; i < TWS_MAX_QS; i++) {
sc->q_head[i] = NULL;
sc->q_tail[i] = NULL;
}
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index 293b0c72587f..e58d6a674ec0 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -1231,12 +1231,14 @@ static const struct filterops usb_filtops_write = {
.f_isfd = 1,
.f_detach = usb_filter_detach,
.f_event = usb_filter_write,
+ .f_copy = knote_triv_copy,
};
static const struct filterops usb_filtops_read = {
.f_isfd = 1,
.f_detach = usb_filter_detach,
.f_event = usb_filter_read,
+ .f_copy = knote_triv_copy,
};
/* ARGSUSED */
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index 460a508a60dc..4961b21180e1 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -120,18 +120,18 @@ vcpu_unlock_one(struct vcpu *vcpu)
vcpu_set_state(vcpu, VCPU_IDLE, false);
}
+#ifndef __amd64__
static int
-vcpu_lock_all(struct vmmdev_softc *sc)
+vcpu_set_state_all(struct vm *vm, enum vcpu_state newstate)
{
struct vcpu *vcpu;
int error;
uint16_t i, j, maxcpus;
error = 0;
- vm_slock_vcpus(sc->vm);
- maxcpus = vm_get_maxcpus(sc->vm);
+ maxcpus = vm_get_maxcpus(vm);
for (i = 0; i < maxcpus; i++) {
- vcpu = vm_vcpu(sc->vm, i);
+ vcpu = vm_vcpu(vm, i);
if (vcpu == NULL)
continue;
error = vcpu_lock_one(vcpu);
@@ -141,16 +141,32 @@ vcpu_lock_all(struct vmmdev_softc *sc)
if (error) {
for (j = 0; j < i; j++) {
- vcpu = vm_vcpu(sc->vm, j);
+ vcpu = vm_vcpu(vm, j);
if (vcpu == NULL)
continue;
vcpu_unlock_one(vcpu);
}
- vm_unlock_vcpus(sc->vm);
}
return (error);
}
+#endif
+
+static int
+vcpu_lock_all(struct vmmdev_softc *sc)
+{
+ int error;
+
+ /*
+ * Serialize vcpu_lock_all() callers. Individual vCPUs are not locked
+ * in a consistent order so we need to serialize to avoid deadlocks.
+ */
+ vm_lock_vcpus(sc->vm);
+ error = vcpu_set_state_all(sc->vm, VCPU_FROZEN);
+ if (error != 0)
+ vm_unlock_vcpus(sc->vm);
+ return (error);
+}
static void
vcpu_unlock_all(struct vmmdev_softc *sc)
diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
index d63a7d4691cf..b2524324584a 100644
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -195,12 +195,14 @@ static const struct filterops cuse_client_kqfilter_read_ops = {
.f_isfd = 1,
.f_detach = cuse_client_kqfilter_read_detach,
.f_event = cuse_client_kqfilter_read_event,
+ .f_copy = knote_triv_copy,
};
static const struct filterops cuse_client_kqfilter_write_ops = {
.f_isfd = 1,
.f_detach = cuse_client_kqfilter_write_detach,
.f_event = cuse_client_kqfilter_write_event,
+ .f_copy = knote_triv_copy,
};
static d_open_t cuse_client_open;
diff --git a/sys/fs/devfs/devfs_dir.c b/sys/fs/devfs/devfs_dir.c
index 3dc87538017d..aad87606e738 100644
--- a/sys/fs/devfs/devfs_dir.c
+++ b/sys/fs/devfs/devfs_dir.c
@@ -162,7 +162,7 @@ int
devfs_pathpath(const char *p1, const char *p2)
{
- for (;;p1++, p2++) {
+ for (;; p1++, p2++) {
if (*p1 != *p2) {
if (*p1 == '/' && *p2 == '\0')
return (1);
diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
index 57b3559731f7..75bc0357571f 100644
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -126,11 +126,13 @@ static const struct filterops fuse_device_rfiltops = {
.f_isfd = 1,
.f_detach = fuse_device_filt_detach,
.f_event = fuse_device_filt_read,
+ .f_copy = knote_triv_copy,
};
static const struct filterops fuse_device_wfiltops = {
.f_isfd = 1,
.f_event = fuse_device_filt_write,
+ .f_copy = knote_triv_copy,
};
/****************************
diff --git a/sys/fs/udf/osta.c b/sys/fs/udf/osta.c
index f79b86993367..1a083d8c26b1 100644
--- a/sys/fs/udf/osta.c
+++ b/sys/fs/udf/osta.c
@@ -383,7 +383,7 @@ int UDFTransName(
int maxFilenameLen;
/* Translate extension, and store it in ext. */
for(index = 0; index<EXT_SIZE &&
- extIndex + index +1 < udfLen; index++ ) {
+ extIndex + index +1 < udfLen; index++) {
current = udfName[extIndex + index + 1];
if (IsIllegal(current) ||
!UnicodeIsPrint(current)) {
@@ -432,7 +432,7 @@ int UDFTransName(
/* Place a translated extension at end, if found. */
if (hasExt) {
newName[newIndex++] = PERIOD;
- for (index = 0;index < localExtIndex ;index++ ) {
+ for (index = 0; index < localExtIndex; index++) {
newName[newIndex++] = ext[index];
}
}
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 26fa14603c85..66fee97a07d5 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -2208,7 +2208,6 @@ unionfs_lock_restart:
vholdnz(tvp);
VI_UNLOCK(vp);
error = VOP_LOCK(tvp, flags);
- vdrop(tvp);
if (error == 0 && (lvp_locked || VTOUNIONFS(vp) == NULL)) {
/*
* After dropping the interlock above, there exists a window
@@ -2234,6 +2233,7 @@ unionfs_lock_restart:
unp = VTOUNIONFS(vp);
if (unp == NULL || unp->un_uppervp != NULL) {
VOP_UNLOCK(tvp);
+ vdrop(tvp);
/*
* If we previously held the lock, the upgrade may
* have temporarily dropped the lock, in which case
@@ -2249,6 +2249,7 @@ unionfs_lock_restart:
goto unionfs_lock_restart;
}
}
+ vdrop(tvp);
return (error);
}
@@ -2259,7 +2260,6 @@ unionfs_unlock(struct vop_unlock_args *ap)
struct vnode *vp;
struct vnode *tvp;
struct unionfs_node *unp;
- int error;
KASSERT_UNIONFS_VNODE(ap->a_vp);
@@ -2271,11 +2271,7 @@ unionfs_unlock(struct vop_unlock_args *ap)
tvp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);
- vholdnz(tvp);
- error = VOP_UNLOCK(tvp);
- vdrop(tvp);
-
- return (error);
+ return (VOP_UNLOCK(tvp));
}
static int
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 27c65f15d5e3..db0bc77a752f 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -82,6 +82,7 @@ static const struct filterops gdev_filterops_vnode = {
.f_isfd = 1,
.f_detach = gdev_filter_detach,
.f_event = gdev_filter_vnode,
+ .f_copy = knote_triv_copy,
};
static struct cdevsw g_dev_cdevsw = {
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 13769af0fbca..14c942942d08 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -92,7 +92,7 @@ struct sysentvec elf32_freebsd_sysvec = {
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
-static Elf32_Brandinfo freebsd_brand_info = {
+static const Elf32_Brandinfo freebsd_brand_info = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_386,
.compat_3_brand = "FreeBSD",
@@ -103,11 +103,11 @@ static Elf32_Brandinfo freebsd_brand_info = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+C_SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
-static Elf32_Brandinfo freebsd_brand_oinfo = {
+static const Elf32_Brandinfo freebsd_brand_oinfo = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_386,
.compat_3_brand = "FreeBSD",
@@ -118,11 +118,11 @@ static Elf32_Brandinfo freebsd_brand_oinfo = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+C_SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_oinfo);
-static Elf32_Brandinfo kfreebsd_brand_info = {
+static const Elf32_Brandinfo kfreebsd_brand_info = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_386,
.compat_3_brand = "FreeBSD",
@@ -133,7 +133,7 @@ static Elf32_Brandinfo kfreebsd_brand_info = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
};
-SYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+C_SYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&kfreebsd_brand_info);
diff --git a/sys/i386/i386/in_cksum_machdep.c b/sys/i386/i386/in_cksum_machdep.c
index 27ab09d82da0..b658d85bc892 100644
--- a/sys/i386/i386/in_cksum_machdep.c
+++ b/sys/i386/i386/in_cksum_machdep.c
@@ -84,7 +84,7 @@ in_cksum_skip(struct mbuf *m, int len, int skip)
}
}
- for (;m && len; m = m->m_next) {
+ for (; m && len; m = m->m_next) {
if (m->m_len == 0)
continue;
w = mtod(m, u_short *);
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 85877bf40997..14b5f64388d2 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -796,7 +796,7 @@ linux_vdso_reloc(char *mapping, Elf_Addr offset)
}
}
-static Elf_Brandnote linux_brandnote = {
+static const Elf_Brandnote linux_brandnote = {
.hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
.hdr.n_descsz = 16, /* XXX at least 16 */
.hdr.n_type = 1,
@@ -805,7 +805,7 @@ static Elf_Brandnote linux_brandnote = {
.trans_osrel = linux_trans_osrel
};
-static Elf32_Brandinfo linux_brand = {
+static const Elf32_Brandinfo linux_brand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
.compat_3_brand = "Linux",
@@ -816,7 +816,7 @@ static Elf32_Brandinfo linux_brand = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-static Elf32_Brandinfo linux_glibc2brand = {
+static const Elf32_Brandinfo linux_glibc2brand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
.compat_3_brand = "Linux",
@@ -827,7 +827,7 @@ static Elf32_Brandinfo linux_glibc2brand = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-static Elf32_Brandinfo linux_muslbrand = {
+static const Elf32_Brandinfo linux_muslbrand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
.compat_3_brand = "Linux",
@@ -839,7 +839,7 @@ static Elf32_Brandinfo linux_muslbrand = {
LINUX_BI_FUTEX_REQUEUE
};
-Elf32_Brandinfo *linux_brandlist[] = {
+const Elf32_Brandinfo *linux_brandlist[] = {
&linux_brand,
&linux_glibc2brand,
&linux_muslbrand,
@@ -849,7 +849,7 @@ Elf32_Brandinfo *linux_brandlist[] = {
static int
linux_elf_modevent(module_t mod, int type, void *data)
{
- Elf32_Brandinfo **brandinfo;
+ const Elf32_Brandinfo **brandinfo;
int error;
struct linux_ioctl_handler **lihp;
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index c53707a1286c..779158b41221 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -231,7 +231,7 @@ static const Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
#define aligned(a, t) (rounddown2((u_long)(a), sizeof(t)) == (u_long)(a))
-Elf_Brandnote __elfN(freebsd_brandnote) = {
+const Elf_Brandnote __elfN(freebsd_brandnote) = {
.hdr.n_namesz = sizeof(FREEBSD_ABI_VENDOR),
.hdr.n_descsz = sizeof(int32_t),
.hdr.n_type = NT_FREEBSD_ABI_TAG,
@@ -254,7 +254,7 @@ __elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel)
static int GNU_KFREEBSD_ABI_DESC = 3;
-Elf_Brandnote __elfN(kfreebsd_brandnote) = {
+const Elf_Brandnote __elfN(kfreebsd_brandnote) = {
.hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
.hdr.n_descsz = 16, /* XXX at least 16 */
.hdr.n_type = 1,
@@ -2831,7 +2831,7 @@ __elfN(parse_notes)(const struct image_params *imgp, const Elf_Note *checknote,
}
if ((const char *)note_end - (const char *)note <
sizeof(Elf_Note)) {
- uprintf("ELF note to short\n");
+ uprintf("ELF note too short\n");
goto retf;
}
if (note->n_namesz != checknote->n_namesz ||
@@ -2839,9 +2839,9 @@ __elfN(parse_notes)(const struct image_params *imgp, const Elf_Note *checknote,
note->n_type != checknote->n_type)
goto nextnote;
note_name = (const char *)(note + 1);
- if (note_name + checknote->n_namesz >=
- (const char *)note_end || strncmp(note_vendor,
- note_name, checknote->n_namesz) != 0)
+ if (note_name + roundup2(note->n_namesz, ELF_NOTE_ROUNDSIZE) +
+ note->n_descsz >= (const char *)note_end ||
+ strncmp(note_vendor, note_name, checknote->n_namesz) != 0)
goto nextnote;
if (cb(note, cb_arg, &res))
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 19118eb7f275..a71a601733e5 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -2486,7 +2486,7 @@ fdunshare(struct thread *td)
if (refcount_load(&p->p_fd->fd_refcnt) == 1)
return;
- tmp = fdcopy(p->p_fd);
+ tmp = fdcopy(p->p_fd, p);
fdescfree(td);
p->p_fd = tmp;
}
@@ -2515,14 +2515,17 @@ pdunshare(struct thread *td)
* this is to ease callers, not catch errors.
*/
struct filedesc *
-fdcopy(struct filedesc *fdp)
+fdcopy(struct filedesc *fdp, struct proc *p1)
{
struct filedesc *newfdp;
struct filedescent *nfde, *ofde;
+ struct file *fp;
int i, lastfile;
+ bool fork_pass;
MPASS(fdp != NULL);
+ fork_pass = false;
newfdp = fdinit();
FILEDESC_SLOCK(fdp);
for (;;) {
@@ -2533,10 +2536,35 @@ fdcopy(struct filedesc *fdp)
fdgrowtable(newfdp, lastfile + 1);
FILEDESC_SLOCK(fdp);
}
- /* copy all passable descriptors (i.e. not kqueue) */
+
+ /*
+ * Copy all passable descriptors (i.e. not kqueue), and
+ * prepare to handle copyable but not passable descriptors
+ * (kqueues).
+ *
+ * The pass to handle copying is performed after all passable
+ * files are installed into the new file descriptor's table,
+ * since kqueues need all referenced file descriptors already
+ * valid, including other kqueues. For the same reason the
+ * copying is done in two passes by itself, first installing
+ * not fully initialized ('empty') copyable files into the new
+ * fd table, and then giving the subsystems a second chance to
+ * really fill the copied file backing structure with the
+ * content.
+ */
newfdp->fd_freefile = fdp->fd_freefile;
FILEDESC_FOREACH_FDE(fdp, i, ofde) {
- if ((ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0 ||
+ const struct fileops *ops;
+
+ ops = ofde->fde_file->f_ops;
+ fp = NULL;
+ if ((ops->fo_flags & DFLAG_FORK) != 0 &&
+ (ofde->fde_flags & UF_FOCLOSE) == 0) {
+ if (ops->fo_fork(newfdp, ofde->fde_file, &fp, p1,
+ curthread) != 0)
+ continue;
+ fork_pass = true;
+ } else if ((ops->fo_flags & DFLAG_PASSABLE) == 0 ||
(ofde->fde_flags & UF_FOCLOSE) != 0 ||
!fhold(ofde->fde_file)) {
if (newfdp->fd_freefile == fdp->fd_freefile)
@@ -2545,11 +2573,30 @@ fdcopy(struct filedesc *fdp)
}
nfde = &newfdp->fd_ofiles[i];
*nfde = *ofde;
+ if (fp != NULL)
+ nfde->fde_file = fp;
filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true);
fdused_init(newfdp, i);
}
MPASS(newfdp->fd_freefile != -1);
FILEDESC_SUNLOCK(fdp);
+
+ /*
+ * Now handle copying kqueues, since all fds, including
+ * kqueues, are in place.
+ */
+ if (__predict_false(fork_pass)) {
+ FILEDESC_FOREACH_FDE(newfdp, i, nfde) {
+ const struct fileops *ops;
+
+ ops = nfde->fde_file->f_ops;
+ if ((ops->fo_flags & DFLAG_FORK) == 0 ||
+ nfde->fde_file == NULL)
+ continue;
+ ops->fo_fork(newfdp, NULL, &nfde->fde_file, p1,
+ curthread);
+ }
+ }
return (newfdp);
}
diff --git a/sys/kern/kern_devctl.c b/sys/kern/kern_devctl.c
index a1696225df32..a37cb23efed8 100644
--- a/sys/kern/kern_devctl.c
+++ b/sys/kern/kern_devctl.c
@@ -130,6 +130,7 @@ static const struct filterops devctl_rfiltops = {
.f_isfd = 1,
.f_detach = filt_devctl_detach,
.f_event = filt_devctl_read,
+ .f_copy = knote_triv_copy,
};
static struct cdev *devctl_dev;
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index a6333d8011b1..1baa24d278bf 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -134,6 +134,7 @@ static fo_kqfilter_t kqueue_kqfilter;
static fo_stat_t kqueue_stat;
static fo_close_t kqueue_close;
static fo_fill_kinfo_t kqueue_fill_kinfo;
+static fo_fork_t kqueue_fork;
static const struct fileops kqueueops = {
.fo_read = invfo_rdwr,
@@ -148,7 +149,9 @@ static const struct fileops kqueueops = {
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
.fo_cmp = file_kcmp_generic,
+ .fo_fork = kqueue_fork,
.fo_fill_kinfo = kqueue_fill_kinfo,
+ .fo_flags = DFLAG_FORK,
};
static int knote_attach(struct knote *kn, struct kqueue *kq);
@@ -176,6 +179,7 @@ static void filt_timerdetach(struct knote *kn);
static void filt_timerstart(struct knote *kn, sbintime_t to);
static void filt_timertouch(struct knote *kn, struct kevent *kev,
u_long type);
+static int filt_timercopy(struct knote *kn, struct proc *p1);
static int filt_timervalidate(struct knote *kn, sbintime_t *to);
static int filt_timer(struct knote *kn, long hint);
static int filt_userattach(struct knote *kn);
@@ -187,11 +191,13 @@ static void filt_usertouch(struct knote *kn, struct kevent *kev,
static const struct filterops file_filtops = {
.f_isfd = 1,
.f_attach = filt_fileattach,
+ .f_copy = knote_triv_copy,
};
static const struct filterops kqread_filtops = {
.f_isfd = 1,
.f_detach = filt_kqdetach,
.f_event = filt_kqueue,
+ .f_copy = knote_triv_copy,
};
/* XXX - move to kern_proc.c? */
static const struct filterops proc_filtops = {
@@ -199,12 +205,14 @@ static const struct filterops proc_filtops = {
.f_attach = filt_procattach,
.f_detach = filt_procdetach,
.f_event = filt_proc,
+ .f_copy = knote_triv_copy,
};
static const struct filterops jail_filtops = {
.f_isfd = 0,
.f_attach = filt_jailattach,
.f_detach = filt_jaildetach,
.f_event = filt_jail,
+ .f_copy = knote_triv_copy,
};
static const struct filterops timer_filtops = {
.f_isfd = 0,
@@ -212,12 +220,14 @@ static const struct filterops timer_filtops = {
.f_detach = filt_timerdetach,
.f_event = filt_timer,
.f_touch = filt_timertouch,
+ .f_copy = filt_timercopy,
};
static const struct filterops user_filtops = {
.f_attach = filt_userattach,
.f_detach = filt_userdetach,
.f_event = filt_user,
.f_touch = filt_usertouch,
+ .f_copy = knote_triv_copy,
};
static uma_zone_t knote_zone;
@@ -347,6 +357,7 @@ filt_nullattach(struct knote *kn)
static const struct filterops null_filtops = {
.f_isfd = 0,
.f_attach = filt_nullattach,
+ .f_copy = knote_triv_copy,
};
/* XXX - make SYSINIT to add these, and move into respective modules. */
@@ -940,6 +951,30 @@ filt_timerattach(struct knote *kn)
return (0);
}
+static int
+filt_timercopy(struct knote *kn, struct proc *p)
+{
+ struct kq_timer_cb_data *kc_src, *kc;
+
+ if (atomic_fetchadd_int(&kq_ncallouts, 1) + 1 > kq_calloutmax) {
+ atomic_subtract_int(&kq_ncallouts, 1);
+ return (ENOMEM);
+ }
+
+ kn->kn_status &= ~KN_DETACHED;
+ kc_src = kn->kn_ptr.p_v;
+ kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK);
+ kc->kn = kn;
+ kc->p = p;
+ kc->flags = kc_src->flags & ~KQ_TIMER_CB_ENQUEUED;
+ kc->next = kc_src->next;
+ kc->to = kc_src->to;
+ kc->cpuid = PCPU_GET(cpuid);
+ callout_init(&kc->c, 1);
+ kqtimer_sched_callout(kc);
+ return (0);
+}
+
static void
filt_timerstart(struct knote *kn, sbintime_t to)
{
@@ -1151,7 +1186,7 @@ int
sys_kqueue(struct thread *td, struct kqueue_args *uap)
{
- return (kern_kqueue(td, 0, NULL));
+ return (kern_kqueue(td, 0, false, NULL));
}
int
@@ -1159,55 +1194,76 @@ sys_kqueuex(struct thread *td, struct kqueuex_args *uap)
{
int flags;
- if ((uap->flags & ~(KQUEUE_CLOEXEC)) != 0)
+ if ((uap->flags & ~(KQUEUE_CLOEXEC | KQUEUE_CPONFORK)) != 0)
return (EINVAL);
flags = 0;
if ((uap->flags & KQUEUE_CLOEXEC) != 0)
flags |= O_CLOEXEC;
- return (kern_kqueue(td, flags, NULL));
+ return (kern_kqueue(td, flags, (uap->flags & KQUEUE_CPONFORK) != 0,
+ NULL));
}
static void
-kqueue_init(struct kqueue *kq)
+kqueue_init(struct kqueue *kq, bool cponfork)
{
mtx_init(&kq->kq_lock, "kqueue", NULL, MTX_DEF | MTX_DUPOK);
TAILQ_INIT(&kq->kq_head);
knlist_init_mtx(&kq->kq_sel.si_note, &kq->kq_lock);
TASK_INIT(&kq->kq_task, 0, kqueue_task, kq);
+ if (cponfork)
+ kq->kq_state |= KQ_CPONFORK;
}
-int
-kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps)
+static int
+kern_kqueue_alloc(struct thread *td, struct filedesc *fdp, int *fdip,
+ struct file **fpp, int flags, struct filecaps *fcaps, bool cponfork,
+ struct kqueue **kqp)
{
- struct filedesc *fdp;
- struct kqueue *kq;
- struct file *fp;
struct ucred *cred;
- int fd, error;
+ struct kqueue *kq;
+ int error;
- fdp = td->td_proc->p_fd;
cred = td->td_ucred;
if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_KQUEUES)))
return (ENOMEM);
- error = falloc_caps(td, &fp, &fd, flags, fcaps);
+ error = fdip != NULL ? falloc_caps(td, fpp, fdip, flags, fcaps) :
+ _falloc_noinstall(td, fpp, 1);
if (error != 0) {
chgkqcnt(cred->cr_ruidinfo, -1, 0);
return (error);
}
/* An extra reference on `fp' has been held for us by falloc(). */
- kq = malloc(sizeof *kq, M_KQUEUE, M_WAITOK | M_ZERO);
- kqueue_init(kq);
+ kq = malloc(sizeof(*kq), M_KQUEUE, M_WAITOK | M_ZERO);
+ kqueue_init(kq, cponfork);
kq->kq_fdp = fdp;
kq->kq_cred = crhold(cred);
- FILEDESC_XLOCK(fdp);
+ if (fdip != NULL)
+ FILEDESC_XLOCK(fdp);
TAILQ_INSERT_HEAD(&fdp->fd_kqlist, kq, kq_list);
- FILEDESC_XUNLOCK(fdp);
+ if (fdip != NULL)
+ FILEDESC_XUNLOCK(fdp);
+
+ finit(*fpp, FREAD | FWRITE, DTYPE_KQUEUE, kq, &kqueueops);
+ *kqp = kq;
+ return (0);
+}
+
+int
+kern_kqueue(struct thread *td, int flags, bool cponfork, struct filecaps *fcaps)
+{
+ struct kqueue *kq;
+ struct file *fp;
+ int fd, error;
+
+ error = kern_kqueue_alloc(td, td->td_proc->p_fd, &fd, &fp, flags,
+ fcaps, cponfork, &kq);
+ if (error != 0)
+ return (error);
- finit(fp, FREAD | FWRITE, DTYPE_KQUEUE, kq, &kqueueops);
fdrop(fp, td);
td->td_retval[0] = fd;
@@ -1488,7 +1544,7 @@ kern_kevent_anonymous(struct thread *td, int nevents,
struct kqueue kq = {};
int error;
- kqueue_init(&kq);
+ kqueue_init(&kq, false);
kq.kq_refcnt = 1;
error = kqueue_kevent(&kq, td, nevents, nevents, k_ops, NULL);
kqueue_drain(&kq, td);
@@ -1576,7 +1632,7 @@ kqueue_fo_release(int filt)
mtx_lock(&filterops_lock);
KASSERT(sysfilt_ops[~filt].for_refcnt > 0,
- ("filter object refcount not valid on release"));
+ ("filter object %d refcount not valid on release", filt));
sysfilt_ops[~filt].for_refcnt--;
mtx_unlock(&filterops_lock);
}
@@ -1855,17 +1911,8 @@ done:
}
static int
-kqueue_acquire(struct file *fp, struct kqueue **kqp)
+kqueue_acquire_ref(struct kqueue *kq)
{
- int error;
- struct kqueue *kq;
-
- error = 0;
-
- kq = fp->f_data;
- if (fp->f_type != DTYPE_KQUEUE || kq == NULL)
- return (EINVAL);
- *kqp = kq;
KQ_LOCK(kq);
if ((kq->kq_state & KQ_CLOSING) == KQ_CLOSING) {
KQ_UNLOCK(kq);
@@ -1873,8 +1920,22 @@ kqueue_acquire(struct file *fp, struct kqueue **kqp)
}
kq->kq_refcnt++;
KQ_UNLOCK(kq);
+ return (0);
+}
- return error;
+static int
+kqueue_acquire(struct file *fp, struct kqueue **kqp)
+{
+ struct kqueue *kq;
+ int error;
+
+ kq = fp->f_data;
+ if (fp->f_type != DTYPE_KQUEUE || kq == NULL)
+ return (EINVAL);
+ error = kqueue_acquire_ref(kq);
+ if (error == 0)
+ *kqp = kq;
+ return (error);
}
static void
@@ -2937,6 +2998,152 @@ noacquire:
return (error);
}
+static int
+kqueue_fork_alloc(struct filedesc *fdp, struct file *fp, struct file **fp1,
+ struct thread *td)
+{
+ struct kqueue *kq, *kq1;
+ int error;
+
+ MPASS(fp->f_type == DTYPE_KQUEUE);
+ kq = fp->f_data;
+ if ((kq->kq_state & KQ_CPONFORK) == 0)
+ return (EOPNOTSUPP);
+ error = kqueue_acquire_ref(kq);
+ if (error != 0)
+ return (error);
+ error = kern_kqueue_alloc(td, fdp, NULL, fp1, 0, NULL, true, &kq1);
+ if (error == 0) {
+ kq1->kq_forksrc = kq;
+ (*fp1)->f_flag = fp->f_flag & (FREAD | FWRITE | FEXEC |
+ O_CLOEXEC | O_CLOFORK);
+ } else {
+ kqueue_release(kq, 0);
+ }
+ return (error);
+}
+
+static void
+kqueue_fork_copy_knote(struct kqueue *kq1, struct knote *kn, struct proc *p1,
+ struct filedesc *fdp)
+{
+ struct knote *kn1;
+ const struct filterops *fop;
+ int error;
+
+ fop = kn->kn_fop;
+ if (fop->f_copy == NULL || (fop->f_isfd &&
+ fdp->fd_files->fdt_ofiles[kn->kn_kevent.ident].fde_file == NULL))
+ return;
+ error = kqueue_expand(kq1, fop, kn->kn_kevent.ident, M_WAITOK);
+ if (error != 0)
+ return;
+
+ kn1 = knote_alloc(M_WAITOK);
+ *kn1 = *kn;
+ kn1->kn_status |= KN_DETACHED;
+ kn1->kn_status &= ~KN_QUEUED;
+ kn1->kn_kq = kq1;
+ error = fop->f_copy(kn1, p1);
+ if (error != 0) {
+ knote_free(kn1);
+ return;
+ }
+ (void)kqueue_fo_find(kn->kn_kevent.filter);
+ if (fop->f_isfd && !fhold(kn1->kn_fp)) {
+ fop->f_detach(kn1);
+ kqueue_fo_release(kn->kn_kevent.filter);
+ knote_free(kn1);
+ return;
+ }
+ if (kn->kn_knlist != NULL)
+ knlist_add(kn->kn_knlist, kn1, 0);
+ KQ_LOCK(kq1);
+ knote_attach(kn1, kq1);
+ kn1->kn_influx = 0;
+ if ((kn->kn_status & KN_QUEUED) != 0)
+ knote_enqueue(kn1);
+ KQ_UNLOCK(kq1);
+}
+
+static void
+kqueue_fork_copy_list(struct klist *knlist, struct knote *marker,
+ struct kqueue *kq, struct kqueue *kq1, struct proc *p1,
+ struct filedesc *fdp)
+{
+ struct knote *kn;
+
+ KQ_OWNED(kq);
+ kn = SLIST_FIRST(knlist);
+ while (kn != NULL) {
+ if ((kn->kn_status & KN_DETACHED) != 0 ||
+ (kn_in_flux(kn) && (kn->kn_status & KN_SCAN) == 0)) {
+ kn = SLIST_NEXT(kn, kn_link);
+ continue;
+ }
+ kn_enter_flux(kn);
+ SLIST_INSERT_AFTER(kn, marker, kn_link);
+ KQ_UNLOCK(kq);
+ kqueue_fork_copy_knote(kq1, kn, p1, fdp);
+ KQ_LOCK(kq);
+ kn_leave_flux(kn);
+ kn = SLIST_NEXT(marker, kn_link);
+ /* XXXKIB switch kn_link to LIST? */
+ SLIST_REMOVE(knlist, marker, knote, kn_link);
+ }
+}
+
+static int
+kqueue_fork_copy(struct filedesc *fdp, struct file *fp, struct file *fp1,
+ struct proc *p1, struct thread *td)
+{
+ struct kqueue *kq, *kq1;
+ struct knote *marker;
+ int error, i;
+
+ error = 0;
+ MPASS(fp == NULL);
+ MPASS(fp1->f_type == DTYPE_KQUEUE);
+
+ kq1 = fp1->f_data;
+ kq = kq1->kq_forksrc;
+ marker = knote_alloc(M_WAITOK);
+ marker->kn_status = KN_MARKER;
+
+ KQ_LOCK(kq);
+ for (i = 0; i < kq->kq_knlistsize; i++) {
+ kqueue_fork_copy_list(&kq->kq_knlist[i], marker, kq, kq1,
+ p1, fdp);
+ }
+ if (kq->kq_knhashmask != 0) {
+ for (i = 0; i <= kq->kq_knhashmask; i++) {
+ kqueue_fork_copy_list(&kq->kq_knhash[i], marker, kq,
+ kq1, p1, fdp);
+ }
+ }
+ kqueue_release(kq, 1);
+ kq1->kq_forksrc = NULL;
+ KQ_UNLOCK(kq);
+
+ knote_free(marker);
+ return (error);
+}
+
+static int
+kqueue_fork(struct filedesc *fdp, struct file *fp, struct file **fp1,
+ struct proc *p1, struct thread *td)
+{
+ if (*fp1 == NULL)
+ return (kqueue_fork_alloc(fdp, fp, fp1, td));
+ return (kqueue_fork_copy(fdp, fp, *fp1, p1, td));
+}
+
+int
+knote_triv_copy(struct knote *kn __unused, struct proc *p1 __unused)
+{
+ return (0);
+}
+
struct knote_status_export_bit {
int kn_status_bit;
int knt_status_bit;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index ab8ed32ad189..c4b1c8201ff2 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -807,7 +807,7 @@ kern_abort2(struct thread *td, const char *why, int nargs, void **uargs)
}
if (nargs > 0) {
sbuf_putc(sb, '(');
- for (i = 0;i < nargs; i++)
+ for (i = 0; i < nargs; i++)
sbuf_printf(sb, "%s%p", i == 0 ? "" : ", ", uargs[i]);
sbuf_putc(sb, ')');
}
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 7f6abae187b3..8b237b6dbd17 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -423,7 +423,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
pd = pdshare(p1->p_pd);
else
pd = pdcopy(p1->p_pd);
- fd = fdcopy(p1->p_fd);
+ fd = fdcopy(p1->p_fd, p2);
fdtol = NULL;
} else {
if (fr->fr_flags2 & FR2_SHARE_PATHS)
diff --git a/sys/kern/kern_jaildesc.c b/sys/kern/kern_jaildesc.c
index 3f322b271400..a564393d3366 100644
--- a/sys/kern/kern_jaildesc.c
+++ b/sys/kern/kern_jaildesc.c
@@ -344,6 +344,7 @@ static const struct filterops jaildesc_kqops = {
.f_isfd = 1,
.f_detach = jaildesc_kqops_detach,
.f_event = jaildesc_kqops_event,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index e919b15543b2..fcbfbe64f854 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -1302,7 +1302,7 @@ mallocinit(void *dummy)
#endif
align, UMA_ZONE_MALLOC);
}
- for (;i <= size; i+= KMEM_ZBASE)
+ for (; i <= size; i+= KMEM_ZBASE)
kmemsize[i >> KMEM_ZSHIFT] = indx;
}
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 21f765b17f62..a55f3c761449 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -124,6 +124,7 @@ const struct filterops sig_filtops = {
.f_attach = filt_sigattach,
.f_detach = filt_sigdetach,
.f_event = filt_signal,
+ .f_copy = knote_triv_copy,
};
static int kern_forcesigexit = 1;
diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c
index 07a9cc0f57be..c4d0223d484f 100644
--- a/sys/kern/subr_devstat.c
+++ b/sys/kern/subr_devstat.c
@@ -415,7 +415,7 @@ sysctl_devstat(SYSCTL_HANDLER_ARGS)
if (error != 0)
return (error);
- for (;nds != NULL;) {
+ while (nds != NULL) {
error = SYSCTL_OUT(req, nds, sizeof(struct devstat));
if (error != 0)
return (error);
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c
index 5380902e602f..aac35a56130e 100644
--- a/sys/kern/subr_log.c
+++ b/sys/kern/subr_log.c
@@ -79,6 +79,7 @@ static const struct filterops log_read_filterops = {
.f_attach = NULL,
.f_detach = logkqdetach,
.f_event = logkqread,
+ .f_copy = knote_triv_copy,
};
static struct logsoftc {
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index db0ceb17b9f0..e2070ae3f865 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -766,7 +766,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
- for (q=p;*q;q++)
+ for (q = p; *q; q++)
PCHAR(*q);
}
break;
diff --git a/sys/kern/sys_eventfd.c b/sys/kern/sys_eventfd.c
index c2a0f67cae85..04ed107c933d 100644
--- a/sys/kern/sys_eventfd.c
+++ b/sys/kern/sys_eventfd.c
@@ -85,13 +85,16 @@ static int filt_eventfdwrite(struct knote *kn, long hint);
static const struct filterops eventfd_rfiltops = {
.f_isfd = 1,
.f_detach = filt_eventfddetach,
- .f_event = filt_eventfdread
+ .f_event = filt_eventfdread,
+ .f_copy = knote_triv_copy,
};
+
static const struct filterops eventfd_wfiltops = {
.f_isfd = 1,
.f_detach = filt_eventfddetach,
- .f_event = filt_eventfdwrite
+ .f_event = filt_eventfdwrite,
+ .f_copy = knote_triv_copy,
};
struct eventfd {
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 57ebe8dc85f0..6531cea31423 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -181,20 +181,23 @@ static int filt_pipedump(struct proc *p, struct knote *kn,
static const struct filterops pipe_nfiltops = {
.f_isfd = 1,
.f_detach = filt_pipedetach_notsup,
- .f_event = filt_pipenotsup
+ .f_event = filt_pipenotsup,
/* no userdump */
+ .f_copy = knote_triv_copy,
};
static const struct filterops pipe_rfiltops = {
.f_isfd = 1,
.f_detach = filt_pipedetach,
.f_event = filt_piperead,
.f_userdump = filt_pipedump,
+ .f_copy = knote_triv_copy,
};
static const struct filterops pipe_wfiltops = {
.f_isfd = 1,
.f_detach = filt_pipedetach,
.f_event = filt_pipewrite,
.f_userdump = filt_pipedump,
+ .f_copy = knote_triv_copy,
};
/*
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index acaf1241cb2e..c5db21544b0f 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -486,6 +486,7 @@ static const struct filterops procdesc_kqops = {
.f_isfd = 1,
.f_detach = procdesc_kqops_detach,
.f_event = procdesc_kqops_event,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index c8e2c561b7cf..067471eb949a 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -754,12 +754,14 @@ static const struct filterops tty_kqops_read = {
.f_isfd = 1,
.f_detach = tty_kqops_read_detach,
.f_event = tty_kqops_read_event,
+ .f_copy = knote_triv_copy,
};
static const struct filterops tty_kqops_write = {
.f_isfd = 1,
.f_detach = tty_kqops_write_detach,
.f_event = tty_kqops_write_event,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index 1291770a9ccb..2672935c2d89 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -491,11 +491,13 @@ static const struct filterops pts_kqops_read = {
.f_isfd = 1,
.f_detach = pts_kqops_read_detach,
.f_event = pts_kqops_read_event,
+ .f_copy = knote_triv_copy,
};
static const struct filterops pts_kqops_write = {
.f_isfd = 1,
.f_detach = pts_kqops_write_detach,
.f_event = pts_kqops_write_event,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index a8aec397b352..4c1bb1ff228e 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -281,11 +281,13 @@ static const struct filterops mq_rfiltops = {
.f_isfd = 1,
.f_detach = filt_mqdetach,
.f_event = filt_mqread,
+ .f_copy = knote_triv_copy,
};
static const struct filterops mq_wfiltops = {
.f_isfd = 1,
.f_detach = filt_mqdetach,
.f_event = filt_mqwrite,
+ .f_copy = knote_triv_copy,
};
/*
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index fe2d8d056062..eb9544628137 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -191,16 +191,19 @@ static const struct filterops soread_filtops = {
.f_isfd = 1,
.f_detach = filt_sordetach,
.f_event = filt_soread,
+ .f_copy = knote_triv_copy,
};
static const struct filterops sowrite_filtops = {
.f_isfd = 1,
.f_detach = filt_sowdetach,
.f_event = filt_sowrite,
+ .f_copy = knote_triv_copy,
};
static const struct filterops soempty_filtops = {
.f_isfd = 1,
.f_detach = filt_sowdetach,
.f_event = filt_soempty,
+ .f_copy = knote_triv_copy,
};
so_gen_t so_gencnt; /* generation count for sockets */
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index c5fc1e84ce3f..807271488af2 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1559,15 +1559,19 @@ restart:
mc_init_m(&cmc, control);
SOCK_RECVBUF_LOCK(so);
- MPASS(!(sb->sb_state & SBS_CANTRCVMORE));
-
- if (__predict_false(cmc.mc_len + sb->sb_ccc +
- sb->sb_ctl > sb->sb_hiwat)) {
+ if (__predict_false(
+ (sb->sb_state & SBS_CANTRCVMORE) ||
+ cmc.mc_len + sb->sb_ccc + sb->sb_ctl >
+ sb->sb_hiwat)) {
/*
- * Too bad, while unp_externalize() was
- * failing, the other side had filled
- * the buffer and we can't prepend data
- * back. Losing data!
+ * While the lock was dropped and we
+ * were failing in unp_externalize(),
+ * the peer could has a) disconnected,
+ * b) filled the buffer so that we
+ * can't prepend data back.
+ * These are two edge conditions that
+ * we just can't handle, so lose the
+ * data and return the error.
*/
SOCK_RECVBUF_UNLOCK(so);
SOCK_IO_RECV_UNLOCK(so);
@@ -1851,11 +1855,13 @@ static const struct filterops uipc_write_filtops = {
.f_isfd = 1,
.f_detach = uipc_filt_sowdetach,
.f_event = uipc_filt_sowrite,
+ .f_copy = knote_triv_copy,
};
static const struct filterops uipc_empty_filtops = {
.f_isfd = 1,
.f_detach = uipc_filt_sowdetach,
.f_event = uipc_filt_soempty,
+ .f_copy = knote_triv_copy,
};
static int
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index e63fa4c01434..60916a9fbd32 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -345,12 +345,14 @@ static const struct filterops aio_filtops = {
.f_attach = filt_aioattach,
.f_detach = filt_aiodetach,
.f_event = filt_aio,
+ .f_copy = knote_triv_copy,
};
static const struct filterops lio_filtops = {
.f_isfd = 0,
.f_attach = filt_lioattach,
.f_detach = filt_liodetach,
- .f_event = filt_lio
+ .f_event = filt_lio,
+ .f_copy = knote_triv_copy,
};
static eventhandler_tag exit_tag, exec_tag;
diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c
index b265a5ff3a62..e60d8426ee42 100644
--- a/sys/kern/vfs_inotify.c
+++ b/sys/kern/vfs_inotify.c
@@ -111,6 +111,7 @@ static const struct filterops inotify_rfiltops = {
.f_isfd = 1,
.f_detach = filt_inotifydetach,
.f_event = filt_inotifyevent,
+ .f_copy = knote_triv_copy,
};
static MALLOC_DEFINE(M_INOTIFY, "inotify", "inotify data structures");
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 73e110c05bc1..58975f7ac932 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -6545,6 +6545,7 @@ const struct filterops fs_filtops = {
.f_attach = filt_fsattach,
.f_detach = filt_fsdetach,
.f_event = filt_fsevent,
+ .f_copy = knote_triv_copy,
};
static int
@@ -6624,24 +6625,28 @@ static int filt_vfsvnode(struct knote *kn, long hint);
static void filt_vfsdetach(struct knote *kn);
static int filt_vfsdump(struct proc *p, struct knote *kn,
struct kinfo_knote *kin);
+static int filt_vfscopy(struct knote *kn, struct proc *p1);
static const struct filterops vfsread_filtops = {
.f_isfd = 1,
.f_detach = filt_vfsdetach,
.f_event = filt_vfsread,
.f_userdump = filt_vfsdump,
+ .f_copy = filt_vfscopy,
};
static const struct filterops vfswrite_filtops = {
.f_isfd = 1,
.f_detach = filt_vfsdetach,
.f_event = filt_vfswrite,
.f_userdump = filt_vfsdump,
+ .f_copy = filt_vfscopy,
};
static const struct filterops vfsvnode_filtops = {
.f_isfd = 1,
.f_detach = filt_vfsdetach,
.f_event = filt_vfsvnode,
.f_userdump = filt_vfsdump,
+ .f_copy = filt_vfscopy,
};
static void
@@ -6825,6 +6830,16 @@ filt_vfsdump(struct proc *p, struct knote *kn, struct kinfo_knote *kin)
return (0);
}
+static int
+filt_vfscopy(struct knote *kn, struct proc *p1)
+{
+ struct vnode *vp;
+
+ vp = (struct vnode *)kn->kn_hook;
+ vhold(vp);
+ return (0);
+}
+
int
vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off)
{
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index feb9778c23da..63a0b3260e6d 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -577,6 +577,7 @@ _mlx5ib= mlx5ib
${MACHINE_CPUARCH} == "i386"
_ena= ena
_gve= gve
+_igc= igc
# gcc13 and earlier lack __builtin_bitcountg used by linux emulation
.if !(${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} < 140000)
_iwlwifi= iwlwifi
@@ -747,7 +748,6 @@ _et= et
_ftgpio= ftgpio
_ftwd= ftwd
_exca= exca
-_igc= igc
_io= io
_itwd= itwd
_ix= ix
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index a347dbe2eb73..f598733773d0 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -253,12 +253,14 @@ static const struct filterops bpfread_filtops = {
.f_isfd = 1,
.f_detach = filt_bpfdetach,
.f_event = filt_bpfread,
+ .f_copy = knote_triv_copy,
};
static const struct filterops bpfwrite_filtops = {
.f_isfd = 1,
.f_detach = filt_bpfdetach,
.f_event = filt_bpfwrite,
+ .f_copy = knote_triv_copy,
};
/*
diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c
index c8dbb6aa8893..56bb90cce9bc 100644
--- a/sys/net/if_tuntap.c
+++ b/sys/net/if_tuntap.c
@@ -261,6 +261,7 @@ static const struct filterops tun_read_filterops = {
.f_attach = NULL,
.f_detach = tunkqdetach,
.f_event = tunkqread,
+ .f_copy = knote_triv_copy,
};
static const struct filterops tun_write_filterops = {
@@ -268,6 +269,7 @@ static const struct filterops tun_write_filterops = {
.f_attach = NULL,
.f_detach = tunkqdetach,
.f_event = tunkqwrite,
+ .f_copy = knote_triv_copy,
};
static struct tuntap_driver {
diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c
index 0181a67ac604..f35712cc8f69 100644
--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c
+++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_rtl.c
@@ -81,9 +81,6 @@ const STRUCT_USB_HOST_ID ubt_rtl_devs[] =
{ USB_VPI(0x0bda, 0xb00c, 0) },
{ USB_VPI(0x0bda, 0xc822, 0) },
- /* Realtek 8822CU Bluetooth devices */
- { USB_VPI(0x13d3, 0x3549, 0) },
-
/* Realtek 8851BE Bluetooth devices */
{ USB_VPI(0x13d3, 0x3600, 0) },
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index f5b20c49ffd2..ba112afbf002 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -159,9 +159,6 @@ static struct ip_moptions *
static int inp_get_source_filters(struct inpcb *, struct sockopt *);
static int inp_join_group(struct inpcb *, struct sockopt *);
static int inp_leave_group(struct inpcb *, struct sockopt *);
-static struct ifnet *
- inp_lookup_mcast_ifp(const struct inpcb *,
- const struct sockaddr_in *, const struct in_addr);
static int inp_block_unblock_source(struct inpcb *, struct sockopt *);
static int inp_set_multicast_if(struct inpcb *, struct sockopt *);
static int inp_set_source_filters(struct inpcb *, struct sockopt *);
@@ -1832,69 +1829,55 @@ inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
}
/*
- * Look up the ifnet to use for a multicast group membership,
- * given the IPv4 address of an interface, and the IPv4 group address.
- *
- * This routine exists to support legacy multicast applications
- * which do not understand that multicast memberships are scoped to
- * specific physical links in the networking stack, or which need
- * to join link-scope groups before IPv4 addresses are configured.
- *
- * Use this socket's current FIB number for any required FIB lookup.
- * If ina is INADDR_ANY, look up the group address in the unicast FIB,
- * and use its ifp; usually, this points to the default next-hop.
- *
- * If the FIB lookup fails, attempt to use the first non-loopback
- * interface with multicast capability in the system as a
- * last resort. The legacy IPv4 ASM API requires that we do
- * this in order to allow groups to be joined when the routing
- * table has not yet been populated during boot.
- *
- * Returns NULL if no ifp could be found, otherwise return referenced ifp.
+ * Look up the ifnet to join a multicast group membership via legacy
+ * IP_ADD_MEMBERSHIP or via more modern MCAST_JOIN_GROUP.
*
- * FUTURE: Implement IPv4 source-address selection.
+ * If the interface index was specified explicitly, just use it. If the
+ * address was specified (legacy), try to find matching interface. Else
+ * (index == 0 && no address) do a route lookup. If that fails for a modern
+ * MCAST_JOIN_GROUP return failure, for legacy IP_ADD_MEMBERSHIP find first
+ * multicast capable interface.
*/
static struct ifnet *
-inp_lookup_mcast_ifp(const struct inpcb *inp,
- const struct sockaddr_in *gsin, const struct in_addr ina)
+inp_lookup_mcast_ifp(const struct inpcb *inp, const struct in_addr maddr,
+const struct in_addr *ina, const u_int index)
{
struct ifnet *ifp;
struct nhop_object *nh;
NET_EPOCH_ASSERT();
- KASSERT(inp != NULL, ("%s: inp must not be NULL", __func__));
- KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
- KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)),
- ("%s: not multicast", __func__));
- ifp = NULL;
- if (!in_nullhost(ina)) {
- INADDR_TO_IFP(ina, ifp);
+ if (index != 0)
+ return (ifnet_byindex_ref(index));
+
+ if (ina != NULL && !in_nullhost(*ina)) {
+ INADDR_TO_IFP(*ina, ifp);
if (ifp != NULL)
if_ref(ifp);
- } else {
- nh = fib4_lookup(inp->inp_inc.inc_fibnum, gsin->sin_addr, 0, NHR_NONE, 0);
- if (nh != NULL) {
- ifp = nh->nh_ifp;
- if_ref(ifp);
- } else {
- struct in_ifaddr *ia;
- struct ifnet *mifp;
-
- mifp = NULL;
- CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- mifp = ia->ia_ifp;
- if (!(mifp->if_flags & IFF_LOOPBACK) &&
- (mifp->if_flags & IFF_MULTICAST)) {
- ifp = mifp;
- if_ref(ifp);
- break;
- }
+ return (ifp);
+ }
+
+ nh = fib4_lookup(inp->inp_inc.inc_fibnum, maddr, 0, NHR_NONE, 0);
+ if (nh != NULL) {
+ ifp = nh->nh_ifp;
+ if_ref(ifp);
+ return (ifp);
+ }
+
+ if (ina != NULL) {
+ struct in_ifaddr *ia;
+
+ CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK) &&
+ (ia->ia_ifp->if_flags & IFF_MULTICAST)) {
+ ifp = ia->ia_ifp;
+ if_ref(ifp);
+ return (ifp);
}
}
}
- return (ifp);
+ return (NULL);
}
/*
@@ -1926,13 +1909,13 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
switch (sopt->sopt_name) {
case IP_ADD_MEMBERSHIP: {
struct ip_mreqn mreqn;
+ bool mreq;
- if (sopt->sopt_valsize == sizeof(struct ip_mreqn))
- error = sooptcopyin(sopt, &mreqn,
- sizeof(struct ip_mreqn), sizeof(struct ip_mreqn));
- else
- error = sooptcopyin(sopt, &mreqn,
- sizeof(struct ip_mreq), sizeof(struct ip_mreq));
+ mreq = (sopt->sopt_valsize != sizeof(struct ip_mreqn));
+
+ error = sooptcopyin(sopt, &mreqn,
+ mreq ? sizeof(struct ip_mreq) : sizeof(struct ip_mreqn),
+ mreq ? sizeof(struct ip_mreq) : sizeof(struct ip_mreqn));
if (error)
return (error);
@@ -1943,12 +1926,9 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
return (EINVAL);
NET_EPOCH_ENTER(et);
- if (sopt->sopt_valsize == sizeof(struct ip_mreqn) &&
- mreqn.imr_ifindex != 0)
- ifp = ifnet_byindex_ref(mreqn.imr_ifindex);
- else
- ifp = inp_lookup_mcast_ifp(inp, &gsa->sin,
- mreqn.imr_address);
+ ifp = inp_lookup_mcast_ifp(inp, mreqn.imr_multiaddr,
+ mreq ? &mreqn.imr_address : NULL,
+ mreq ? 0 : mreqn.imr_ifindex);
NET_EPOCH_EXIT(et);
break;
}
@@ -1971,8 +1951,8 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
ssa->sin.sin_addr = mreqs.imr_sourceaddr;
NET_EPOCH_ENTER(et);
- ifp = inp_lookup_mcast_ifp(inp, &gsa->sin,
- mreqs.imr_interface);
+ ifp = inp_lookup_mcast_ifp(inp, mreqs.imr_multiaddr,
+ &mreqs.imr_interface, 0);
NET_EPOCH_EXIT(et);
CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p",
__func__, ntohl(mreqs.imr_interface.s_addr), ifp);
@@ -2013,7 +1993,8 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
return (EINVAL);
NET_EPOCH_ENTER(et);
- ifp = ifnet_byindex_ref(gsr.gsr_interface);
+ ifp = inp_lookup_mcast_ifp(inp, gsa->sin.sin_addr, NULL,
+ gsr.gsr_interface);
NET_EPOCH_EXIT(et);
if (ifp == NULL)
return (EADDRNOTAVAIL);
diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
index c143d74a2f45..41f0a328daec 100644
--- a/sys/netinet/libalias/alias_db.c
+++ b/sys/netinet/libalias/alias_db.c
@@ -2181,7 +2181,7 @@ LibAliasInit(struct libalias *la)
#undef malloc /* XXX: ugly */
la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
#else
- la = calloc(sizeof *la, 1);
+ la = calloc(1, sizeof *la);
if (la == NULL)
return (la);
#endif
diff --git a/sys/netinet/siftr.c b/sys/netinet/siftr.c
index 374b5595fcbc..5b89ca026e85 100644
--- a/sys/netinet/siftr.c
+++ b/sys/netinet/siftr.c
@@ -519,7 +519,7 @@ siftr_pkt_manager_thread(void *arg)
if (log_buf != NULL) {
alq_post_flags(siftr_alq, log_buf, 0);
}
- for (;cnt > 0; cnt--) {
+ for (; cnt > 0; cnt--) {
pkt_node = STAILQ_FIRST(&tmp_pkt_queue);
STAILQ_REMOVE_HEAD(&tmp_pkt_queue, nodes);
free(pkt_node, M_SIFTR_PKTNODE);
diff --git a/sys/netinet/tcp_hpts_test.c b/sys/netinet/tcp_hpts_test.c
index bab5827e0572..c5dc9cb5b03b 100644
--- a/sys/netinet/tcp_hpts_test.c
+++ b/sys/netinet/tcp_hpts_test.c
@@ -27,6 +27,7 @@
#include <tests/ktest.h>
#include <sys/cdefs.h>
+#include "opt_inet.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
@@ -119,6 +120,8 @@ SYSCTL_INT(_net_inet_tcp_hpts_test, OID_AUTO, exit_on_failure, CTLFLAG_RW,
} \
} while (0)
+#ifdef TCP_HPTS_KTEST
+
static void
dump_hpts_entry(struct ktest_test_context *ctx, struct tcp_hpts_entry *hpts)
{
@@ -1658,5 +1661,22 @@ static const struct ktest_test_info tests[] = {
KTEST_INFO(generation_count_validation),
};
+#else /* TCP_HPTS_KTEST */
+
+/*
+ * Stub to indicate that the TCP HPTS ktest is not enabled.
+ */
+KTEST_FUNC(module_load_without_tests)
+{
+ KTEST_LOG(ctx, "Warning: TCP HPTS ktest is not enabled");
+ return (0);
+}
+
+static const struct ktest_test_info tests[] = {
+ KTEST_INFO(module_load_without_tests),
+};
+
+#endif
+
KTEST_MODULE_DECLARE(ktest_tcphpts, tests);
KTEST_MODULE_DEPEND(ktest_tcphpts, tcphpts);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index dd27ec77c1af..2146b0cac48f 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -219,7 +219,7 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_do_autorcvbuf), 0,
"Enable automatic receive buffer sizing");
-VNET_DEFINE(int, tcp_autorcvbuf_max) = 2*1024*1024;
+VNET_DEFINE(int, tcp_autorcvbuf_max) = 8*1024*1024;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_max), 0,
"Max size of automatic receive buffer");
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 2dfb7faf56e3..208f72c4661c 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -123,7 +123,7 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_inc, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_inc), 0,
"Incrementor step size of automatic send buffer");
-VNET_DEFINE(int, tcp_autosndbuf_max) = 2*1024*1024;
+VNET_DEFINE(int, tcp_autosndbuf_max) = 8*1024*1024;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
"Max size of automatic send buffer");
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index c7962b57a69e..0320479e882e 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -6864,6 +6864,18 @@ rack_mark_lost(struct tcpcb *tp,
}
}
+static inline void
+rack_mark_nolonger_lost(struct tcp_rack *rack, struct rack_sendmap *rsm)
+{
+ KASSERT((rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)),
+ ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
+ rsm->r_flags &= ~RACK_WAS_LOST;
+ if (rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start))
+ rack->r_ctl.rc_considered_lost -= rsm->r_end - rsm->r_start;
+ else
+ rack->r_ctl.rc_considered_lost = 0;
+}
+
/*
* RACK Timer, here we simply do logging and house keeping.
* the normal rack_output() function will call the
@@ -8130,13 +8142,7 @@ rack_update_rsm(struct tcpcb *tp, struct tcp_rack *rack,
* remove the lost desgination and reduce the
* bytes considered lost.
*/
- rsm->r_flags &= ~RACK_WAS_LOST;
- KASSERT((rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)),
- ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
- if (rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start))
- rack->r_ctl.rc_considered_lost -= rsm->r_end - rsm->r_start;
- else
- rack->r_ctl.rc_considered_lost = 0;
+ rack_mark_nolonger_lost(rack, rsm);
}
idx = rsm->r_rtr_cnt - 1;
rsm->r_tim_lastsent[idx] = ts;
@@ -9492,6 +9498,11 @@ do_rest_ofb:
if (rsm->r_flags & RACK_WAS_LOST) {
int my_chg;
+ /*
+ * Note here we do not use our rack_mark_nolonger_lost() function
+ * since we are moving our data pointer around and the
+ * ack'ed side is already not considered lost.
+ */
my_chg = (nrsm->r_end - nrsm->r_start);
KASSERT((rack->r_ctl.rc_considered_lost >= my_chg),
("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
@@ -9659,16 +9670,11 @@ do_rest_ofb:
changed += (rsm->r_end - rsm->r_start);
/* You get a count for acking a whole segment or more */
if (rsm->r_flags & RACK_WAS_LOST) {
- int my_chg;
-
- my_chg = (rsm->r_end - rsm->r_start);
- rsm->r_flags &= ~RACK_WAS_LOST;
- KASSERT((rack->r_ctl.rc_considered_lost >= my_chg),
- ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
- if (my_chg <= rack->r_ctl.rc_considered_lost)
- rack->r_ctl.rc_considered_lost -= my_chg;
- else
- rack->r_ctl.rc_considered_lost = 0;
+ /*
+ * Here we can use the inline function since
+ * the rsm is truly marked lost and now no longer lost.
+ */
+ rack_mark_nolonger_lost(rack, rsm);
}
rack->r_ctl.rc_sacked += (rsm->r_end - rsm->r_start);
if (rsm->r_in_tmap) /* should be true */
@@ -9851,6 +9857,10 @@ do_rest_ofb:
if (rsm->r_flags & RACK_WAS_LOST) {
int my_chg;
+ /*
+ * Note here we are using hookery again so we can't
+ * use our rack_mark_nolonger_lost() function.
+ */
my_chg = (nrsm->r_end - nrsm->r_start);
KASSERT((rack->r_ctl.rc_considered_lost >= my_chg),
("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
@@ -9952,16 +9962,10 @@ do_rest_ofb:
rack_update_rtt(tp, rack, rsm, to, cts, SACKED, 0);
changed += (rsm->r_end - rsm->r_start);
if (rsm->r_flags & RACK_WAS_LOST) {
- int my_chg;
-
- my_chg = (rsm->r_end - rsm->r_start);
- rsm->r_flags &= ~RACK_WAS_LOST;
- KASSERT((rack->r_ctl.rc_considered_lost >= my_chg),
- ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
- if (my_chg <= rack->r_ctl.rc_considered_lost)
- rack->r_ctl.rc_considered_lost -= my_chg;
- else
- rack->r_ctl.rc_considered_lost = 0;
+ /*
+ * Here it is safe to use our function.
+ */
+ rack_mark_nolonger_lost(rack, rsm);
}
rack->r_ctl.rc_sacked += (rsm->r_end - rsm->r_start);
@@ -10362,13 +10366,7 @@ more:
* and yet before retransmitting we get an ack
* which can happen due to reordering.
*/
- rsm->r_flags &= ~RACK_WAS_LOST;
- KASSERT((rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)),
- ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack));
- if (rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start))
- rack->r_ctl.rc_considered_lost -= rsm->r_end - rsm->r_start;
- else
- rack->r_ctl.rc_considered_lost = 0;
+ rack_mark_nolonger_lost(rack, rsm);
}
rack_log_map_chg(tp, rack, NULL, rsm, NULL, MAP_FREE, rsm->r_end, __LINE__);
rack->r_ctl.rc_holes_rxt -= rsm->r_rtr_bytes;
@@ -10476,12 +10474,7 @@ more:
* which can happen due to reordering. In this
* case its only a partial ack of the send.
*/
- KASSERT((rack->r_ctl.rc_considered_lost >= (th_ack - rsm->r_start)),
- ("rsm:%p rack:%p rc_considered_lost goes negative th_ack:%u", rsm, rack, th_ack));
- if (rack->r_ctl.rc_considered_lost >= (th_ack - rsm->r_start))
- rack->r_ctl.rc_considered_lost -= th_ack - rsm->r_start;
- else
- rack->r_ctl.rc_considered_lost = 0;
+ rack_mark_nolonger_lost(rack, rsm);
}
/*
* Clear the dup ack count for
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index f842a5678fa1..be20fb44a820 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1046,6 +1046,8 @@ abort:
*
* On syncache_socket() success the newly created socket
* has its underlying inp locked.
+ *
+ * *lsop is updated, if and only if 1 is returned.
*/
int
syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
@@ -1094,12 +1096,14 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
SCH_UNLOCK(sch);
TCPSTAT_INC(tcps_sc_spurcookie);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected "
"(syncookies disabled)\n",
s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
if (sch->sch_last_overflow <
time_uptime - SYNCOOKIE_LIFETIME) {
@@ -1109,12 +1113,14 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
SCH_UNLOCK(sch);
TCPSTAT_INC(tcps_sc_spurcookie);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected "
"(no syncache entry)\n",
s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
SCH_UNLOCK(sch);
}
@@ -1128,11 +1134,13 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
TCPSTAT_INC(tcps_sc_recvcookie);
} else {
TCPSTAT_INC(tcps_sc_failcookie);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Segment failed "
"SYNCOOKIE authentication, segment rejected "
"(probably spoofed)\n", s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
/* If received ACK has MD5 signature, check it. */
@@ -1206,9 +1214,9 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"%s; %s: SEG.TSval %u < TS.Recent %u, "
"segment dropped\n", s, __func__,
to->to_tsval, sc->sc_tsreflect);
- free(s, M_TCPLOG);
}
SCH_UNLOCK(sch);
+ free(s, M_TCPLOG);
return (-1); /* Do not send RST */
}
@@ -1225,7 +1233,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"expected, segment processed normally\n",
s, __func__);
free(s, M_TCPLOG);
- s = NULL;
}
}
@@ -1312,16 +1319,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
if (sc != &scs)
syncache_free(sc);
return (1);
-failed:
- if (sc != NULL) {
- TCPSTATES_DEC(TCPS_SYN_RECEIVED);
- if (sc != &scs)
- syncache_free(sc);
- }
- if (s != NULL)
- free(s, M_TCPLOG);
- *lsop = NULL;
- return (0);
}
static struct socket *
diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c
index b3f52322425f..d522f9da0fbe 100644
--- a/sys/netpfil/ipfw/ip_dummynet.c
+++ b/sys/netpfil/ipfw/ip_dummynet.c
@@ -1150,7 +1150,7 @@ copy_data_helper(void *_o, void *_arg)
return 0; /* not a pipe */
/* see if the object is within one of our ranges */
- for (;r < lim; r += 2) {
+ for (; r < lim; r += 2) {
if (n < r[0] || n > r[1])
continue;
/* Found a valid entry, copy and we are done */
@@ -1183,7 +1183,7 @@ copy_data_helper(void *_o, void *_arg)
if (n >= DN_MAX_ID)
return 0;
/* see if the object is within one of our ranges */
- for (;r < lim; r += 2) {
+ for (; r < lim; r += 2) {
if (n < r[0] || n > r[1])
continue;
if (copy_flowset(a, fs, 0))
diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c
index e1118713bff0..6b904c02ea15 100644
--- a/sys/powerpc/powerpc/elf32_machdep.c
+++ b/sys/powerpc/powerpc/elf32_machdep.c
@@ -143,7 +143,7 @@ struct sysentvec elf32_freebsd_sysvec = {
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
-static Elf32_Brandinfo freebsd_brand_info = {
+static const Elf32_Brandinfo freebsd_brand_info = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_PPC,
.compat_3_brand = "FreeBSD",
@@ -158,11 +158,11 @@ static Elf32_Brandinfo freebsd_brand_info = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+C_SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
-static Elf32_Brandinfo freebsd_brand_oinfo = {
+static const Elf32_Brandinfo freebsd_brand_oinfo = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_PPC,
.compat_3_brand = "FreeBSD",
@@ -173,7 +173,7 @@ static Elf32_Brandinfo freebsd_brand_oinfo = {
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+C_SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_oinfo);
diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c
index a999f742caeb..0be40bed69cb 100644
--- a/sys/powerpc/powerpc/elf64_machdep.c
+++ b/sys/powerpc/powerpc/elf64_machdep.c
@@ -154,7 +154,7 @@ static bool ppc64_elfv1_header_match(const struct image_params *params,
static bool ppc64_elfv2_header_match(const struct image_params *params,
const int32_t *, const uint32_t *);
-static Elf64_Brandinfo freebsd_brand_info_elfv1 = {
+static const Elf64_Brandinfo freebsd_brand_info_elfv1 = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_PPC64,
.compat_3_brand = "FreeBSD",
@@ -166,11 +166,11 @@ static Elf64_Brandinfo freebsd_brand_info_elfv1 = {
.header_supported = &ppc64_elfv1_header_match
};
-SYSINIT(elf64v1, SI_SUB_EXEC, SI_ORDER_ANY,
+C_SYSINIT(elf64v1, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info_elfv1);
-static Elf64_Brandinfo freebsd_brand_info_elfv2 = {
+static const Elf64_Brandinfo freebsd_brand_info_elfv2 = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_PPC64,
.compat_3_brand = "FreeBSD",
@@ -182,11 +182,11 @@ static Elf64_Brandinfo freebsd_brand_info_elfv2 = {
.header_supported = &ppc64_elfv2_header_match
};
-SYSINIT(elf64v2, SI_SUB_EXEC, SI_ORDER_ANY,
+C_SYSINIT(elf64v2, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info_elfv2);
-static Elf64_Brandinfo freebsd_brand_oinfo = {
+static const Elf64_Brandinfo freebsd_brand_oinfo = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_PPC64,
.compat_3_brand = "FreeBSD",
@@ -198,7 +198,7 @@ static Elf64_Brandinfo freebsd_brand_oinfo = {
.header_supported = &ppc64_elfv1_header_match
};
-SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+C_SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
diff --git a/sys/riscv/include/vmm.h b/sys/riscv/include/vmm.h
index bc00474ed0fd..e227dd825966 100644
--- a/sys/riscv/include/vmm.h
+++ b/sys/riscv/include/vmm.h
@@ -149,7 +149,7 @@ DECLARE_VMMOPS_FUNC(void, vmspace_free, (struct vmspace *vmspace));
int vm_create(const char *name, struct vm **retvm);
struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
void vm_disable_vcpu_creation(struct vm *vm);
-void vm_slock_vcpus(struct vm *vm);
+void vm_lock_vcpus(struct vm *vm);
void vm_unlock_vcpus(struct vm *vm);
void vm_destroy(struct vm *vm);
int vm_reinit(struct vm *vm);
diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c
index 67b1fcc4c1a9..5bd4af4c15f8 100644
--- a/sys/riscv/riscv/elf_machdep.c
+++ b/sys/riscv/riscv/elf_machdep.c
@@ -100,7 +100,7 @@ static struct sysentvec elf64_freebsd_sysvec = {
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
-static Elf64_Brandinfo freebsd_brand_info = {
+static const Elf64_Brandinfo freebsd_brand_info = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_RISCV,
.compat_3_brand = "FreeBSD",
@@ -110,7 +110,7 @@ static Elf64_Brandinfo freebsd_brand_info = {
.brand_note = &elf64_freebsd_brandnote,
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
-SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST,
+C_SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST,
(sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_info);
static void
diff --git a/sys/riscv/vmm/vmm.c b/sys/riscv/vmm/vmm.c
index 790dcc576507..4c9b1fa53f7a 100644
--- a/sys/riscv/vmm/vmm.c
+++ b/sys/riscv/vmm/vmm.c
@@ -346,9 +346,9 @@ vm_alloc_vcpu(struct vm *vm, int vcpuid)
}
void
-vm_slock_vcpus(struct vm *vm)
+vm_lock_vcpus(struct vm *vm)
{
- sx_slock(&vm->vcpus_init_lock);
+ sx_xlock(&vm->vcpus_init_lock);
}
void
diff --git a/sys/security/audit/audit_pipe.c b/sys/security/audit/audit_pipe.c
index fb773fd04297..4d9815467e1a 100644
--- a/sys/security/audit/audit_pipe.c
+++ b/sys/security/audit/audit_pipe.c
@@ -243,6 +243,7 @@ static const struct filterops audit_pipe_read_filterops = {
.f_attach = NULL,
.f_detach = audit_pipe_kqdetach,
.f_event = audit_pipe_kqread,
+ .f_copy = knote_triv_copy,
};
/*
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 084eaafcbdc0..ebbcdb703183 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -228,6 +228,7 @@ struct freebsd11_kevent32 {
/* Flags for kqueuex(2) */
#define KQUEUE_CLOEXEC 0x00000001 /* close on exec */
+#define KQUEUE_CPONFORK 0x00000002 /* copy on fork */
struct knote;
SLIST_HEAD(klist, knote);
@@ -283,6 +284,7 @@ struct filterops {
void (*f_touch)(struct knote *kn, struct kevent *kev, u_long type);
int (*f_userdump)(struct proc *p, struct knote *kn,
struct kinfo_knote *kin);
+ int (*f_copy)(struct knote *kn, struct proc *p1);
};
/*
@@ -346,6 +348,7 @@ struct rwlock;
void knote(struct knlist *list, long hint, int lockflags);
void knote_fork(struct knlist *list, int pid);
+int knote_triv_copy(struct knote *kn, struct proc *p1);
struct knlist *knlist_alloc(struct mtx *lock);
void knlist_detach(struct knlist *knl);
void knlist_add(struct knlist *knl, struct knote *kn, int islocked);
diff --git a/sys/sys/eventvar.h b/sys/sys/eventvar.h
index 7fec444447f9..7cb3269f1fdf 100644
--- a/sys/sys/eventvar.h
+++ b/sys/sys/eventvar.h
@@ -55,12 +55,14 @@ struct kqueue {
#define KQ_CLOSING 0x10
#define KQ_TASKSCHED 0x20 /* task scheduled */
#define KQ_TASKDRAIN 0x40 /* waiting for task to drain */
+#define KQ_CPONFORK 0x80
int kq_knlistsize; /* size of knlist */
struct klist *kq_knlist; /* list of knotes */
u_long kq_knhashmask; /* size of knhash */
struct klist *kq_knhash; /* hash table for knotes */
struct task kq_task;
struct ucred *kq_cred;
+ struct kqueue *kq_forksrc;
};
#endif /* !_SYS_EVENTVAR_H_ */
diff --git a/sys/sys/file.h b/sys/sys/file.h
index c44fd0f28929..e0195c7c6c2a 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -139,6 +139,8 @@ typedef int fo_fspacectl_t(struct file *fp, int cmd,
off_t *offset, off_t *length, int flags,
struct ucred *active_cred, struct thread *td);
typedef int fo_cmp_t(struct file *fp, struct file *fp1, struct thread *td);
+typedef int fo_fork_t(struct filedesc *fdp, struct file *fp, struct file **fp1,
+ struct proc *p1, struct thread *td);
typedef int fo_spare_t(struct file *fp);
typedef int fo_flags_t;
@@ -163,12 +165,14 @@ struct fileops {
fo_fallocate_t *fo_fallocate;
fo_fspacectl_t *fo_fspacectl;
fo_cmp_t *fo_cmp;
+ fo_fork_t *fo_fork;
fo_spare_t *fo_spares[8]; /* Spare slots */
fo_flags_t fo_flags; /* DFLAG_* below */
};
#define DFLAG_PASSABLE 0x01 /* may be passed via unix sockets. */
#define DFLAG_SEEKABLE 0x02 /* seekable / nonsequential */
+#define DFLAG_FORK 0x04 /* copy on fork */
#endif /* _KERNEL */
#if defined(_KERNEL) || defined(_WANT_FILE)
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 0a388c90de26..4817855443af 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -265,7 +265,7 @@ int fdcheckstd(struct thread *td);
void fdclose(struct thread *td, struct file *fp, int idx);
void fdcloseexec(struct thread *td);
void fdsetugidsafety(struct thread *td);
-struct filedesc *fdcopy(struct filedesc *fdp);
+struct filedesc *fdcopy(struct filedesc *fdp, struct proc *p1);
void fdunshare(struct thread *td);
void fdescfree(struct thread *td);
int fdlastfile(struct filedesc *fdp);
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 9e2a233248b4..25ce7871ba7c 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -87,7 +87,7 @@ typedef struct {
const char *interp_newpath;
int flags;
const Elf_Brandnote *brand_note;
- bool (*header_supported)(const struct image_params *,
+ bool (*const header_supported)(const struct image_params *,
const int32_t *, const uint32_t *);
/* High 8 bits of flags is private to the ABI */
#define BI_CAN_EXEC_DYN 0x0001
@@ -132,8 +132,8 @@ bool __elfN(parse_notes)(const struct image_params *, const Elf_Note *,
void __elfN(dump_thread)(struct thread *, void *, size_t *);
extern int __elfN(fallback_brand);
-extern Elf_Brandnote __elfN(freebsd_brandnote);
-extern Elf_Brandnote __elfN(kfreebsd_brandnote);
+extern const Elf_Brandnote __elfN(freebsd_brandnote);
+extern const Elf_Brandnote __elfN(kfreebsd_brandnote);
#endif /* _KERNEL */
#endif /* !_SYS_IMGACT_ELF_H_ */
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index b4593f38f592..739723754b7d 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -62,7 +62,7 @@
#include <sys/_sx.h>
#include <sys/_task.h>
-#define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */
+#define SB_MAX (8*1024*1024) /* default for max chars in sockbuf */
struct ktls_session;
struct mbuf;
diff --git a/sys/sys/sockopt.h b/sys/sys/sockopt.h
index bfe12d8510d7..d2b0ff5ed2c8 100644
--- a/sys/sys/sockopt.h
+++ b/sys/sys/sockopt.h
@@ -57,8 +57,10 @@ struct sockopt {
int sosetopt(struct socket *so, struct sockopt *sopt);
int sogetopt(struct socket *so, struct sockopt *sopt);
-int sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen);
-int sooptcopyout(struct sockopt *sopt, const void *buf, size_t len);
+int __result_use_check sooptcopyin(struct sockopt *sopt, void *buf, size_t len,
+ size_t minlen);
+int __result_use_check sooptcopyout(struct sockopt *sopt, const void *buf,
+ size_t len);
int soopt_getm(struct sockopt *sopt, struct mbuf **mp);
int soopt_mcopyin(struct sockopt *sopt, struct mbuf *m);
int soopt_mcopyout(struct sockopt *sopt, struct mbuf *m);
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index 8237165b84ce..d32690634059 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -211,7 +211,8 @@ int kern_kevent_fp(struct thread *td, struct file *fp, int nchanges,
int nevents, struct kevent_copyops *k_ops,
const struct timespec *timeout);
int kern_kill(struct thread *td, pid_t pid, int signum);
-int kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps);
+int kern_kqueue(struct thread *td, int flags, bool cponfork,
+ struct filecaps *fcaps);
int kern_kldload(struct thread *td, const char *file, int *fileid);
int kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat);
int kern_kldunload(struct thread *td, int fileid, int flags);
diff --git a/sys/vm/vm_domainset.c b/sys/vm/vm_domainset.c
index 9fa17da954f7..c25ed0cc2267 100644
--- a/sys/vm/vm_domainset.c
+++ b/sys/vm/vm_domainset.c
@@ -113,7 +113,6 @@ vm_domainset_iter_interleave(struct vm_domainset_iter *di, int *domain)
int d;
d = di->di_offset % di->di_domain->ds_cnt;
- *di->di_iter = d;
*domain = di->di_domain->ds_order[d];
}
@@ -260,9 +259,14 @@ vm_domainset_iter_page_init(struct vm_domainset_iter *di, struct vm_object *obj,
* are immutable and unsynchronized. Updates can race but pointer
* loads are assumed to be atomic.
*/
- if (obj != NULL && obj->domain.dr_policy != NULL)
+ if (obj != NULL && obj->domain.dr_policy != NULL) {
+ /*
+ * This write lock protects non-atomic increments of the
+ * iterator index in vm_domainset_iter_rr().
+ */
+ VM_OBJECT_ASSERT_WLOCKED(obj);
dr = &obj->domain;
- else
+ } else
dr = &curthread->td_domain;
vm_domainset_iter_init(di, dr->dr_policy, &dr->dr_iter, obj, pindex);
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index e0f1807a1b32..18d789c59281 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -441,19 +441,16 @@ vm_thread_kstack_arena_release(void *arena, vmem_addr_t addr, vmem_size_t size)
* Create the kernel stack for a new thread.
*/
static vm_offset_t
-vm_thread_stack_create(struct domainset *ds, int pages)
+vm_thread_stack_create(struct domainset *ds, int pages, int flags)
{
vm_page_t ma[KSTACK_MAX_PAGES];
struct vm_domainset_iter di;
- int req = VM_ALLOC_NORMAL;
- vm_object_t obj;
+ int req;
vm_offset_t ks;
int domain, i;
- obj = vm_thread_kstack_size_to_obj(pages);
- if (vm_ndomains > 1)
- obj->domain.dr_policy = ds;
- vm_domainset_iter_page_init(&di, obj, 0, &domain, &req);
+ vm_domainset_iter_policy_init(&di, ds, &domain, &flags);
+ req = malloc2vm_flags(flags);
do {
/*
* Get a kernel virtual address for this thread's kstack.
@@ -480,7 +477,7 @@ vm_thread_stack_create(struct domainset *ds, int pages)
vm_page_valid(ma[i]);
pmap_qenter(ks, ma, pages);
return (ks);
- } while (vm_domainset_iter_page(&di, obj, &domain, NULL) == 0);
+ } while (vm_domainset_iter_policy(&di, &domain) == 0);
return (0);
}
@@ -532,15 +529,9 @@ vm_thread_new(struct thread *td, int pages)
ks = 0;
if (pages == kstack_pages && kstack_cache != NULL)
ks = (vm_offset_t)uma_zalloc(kstack_cache, M_NOWAIT);
-
- /*
- * Ensure that kstack objects can draw pages from any memory
- * domain. Otherwise a local memory shortage can block a process
- * swap-in.
- */
if (ks == 0)
ks = vm_thread_stack_create(DOMAINSET_PREF(PCPU_GET(domain)),
- pages);
+ pages, M_NOWAIT);
if (ks == 0)
return (0);
@@ -660,7 +651,8 @@ kstack_import(void *arg, void **store, int cnt, int domain, int flags)
ds = DOMAINSET_PREF(domain);
for (i = 0; i < cnt; i++) {
- store[i] = (void *)vm_thread_stack_create(ds, kstack_pages);
+ store[i] = (void *)vm_thread_stack_create(ds, kstack_pages,
+ flags);
if (store[i] == NULL)
break;
}
diff --git a/sys/x86/acpica/acpi_apm.c b/sys/x86/acpica/acpi_apm.c
index 8e5785cf0ed6..919f76949dd4 100644
--- a/sys/x86/acpica/acpi_apm.c
+++ b/sys/x86/acpica/acpi_apm.c
@@ -64,6 +64,7 @@ static const struct filterops apm_readfiltops = {
.f_isfd = 1,
.f_detach = apmreadfiltdetach,
.f_event = apmreadfilt,
+ .f_copy = knote_triv_copy,
};
static struct cdevsw apm_cdevsw = {