aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-11-07 18:52:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-11-07 18:52:28 +0000
commitc06e7b66a147edf55f4241fbfbfa32856550cd15 (patch)
treebb0300c3cdd104f8d1a9445142dda9913e9bd055 /sys
parentf46f6c14b4bcb6eb831d7d4d1a877a3a4e034c62 (diff)
parent36d2d637dd0ad3227083b5ebd9e38c17c6c934a1 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/conf/GENERIC2
-rw-r--r--sys/amd64/include/cpu.h1
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c6
-rw-r--r--sys/arm/include/cpu.h1
-rw-r--r--sys/arm/include/elf.h2
-rw-r--r--sys/arm64/conf/GENERIC2
-rw-r--r--sys/arm64/include/cpu.h1
-rw-r--r--sys/cam/scsi/scsi_da.c31
-rw-r--r--sys/compat/freebsd32/capabilities.conf1
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h10
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c2
-rw-r--r--sys/compat/freebsd32/freebsd32_systrace_args.c84
-rw-r--r--sys/compat/freebsd32/syscalls.master52
-rw-r--r--sys/compat/linux/linux_common.c7
-rw-r--r--sys/compat/linux/linux_ioctl.c119
-rw-r--r--sys/compat/linux/linux_ioctl.h11
-rw-r--r--sys/compat/linux/linux_socket.c9
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/kern.post.mk4
-rw-r--r--sys/conf/kern.pre.mk6
-rw-r--r--sys/conf/kmod.mk3
-rw-r--r--sys/conf/options3
-rw-r--r--sys/dev/cxgbe/adapter.h2
-rw-r--r--sys/dev/cxgbe/t4_main.c11
-rw-r--r--sys/dev/cxgbe/t4_sge.c121
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c7
-rw-r--r--sys/dev/mrsas/mrsas.h4
-rw-r--r--sys/dev/usb/controller/dwc_otg.c13
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c3
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c37
-rw-r--r--sys/geom/geom_io.c2
-rw-r--r--sys/i386/include/cpu.h1
-rw-r--r--sys/kern/capabilities.conf2
-rw-r--r--sys/kern/init_sysent.c2
-rw-r--r--sys/kern/kern_mutex.c2
-rw-r--r--sys/kern/kern_ubsan.c1650
-rw-r--r--sys/kern/sys_pipe.c5
-rw-r--r--sys/kern/syscalls.master64
-rw-r--r--sys/kern/systrace_args.c72
-rw-r--r--sys/kern/tty.c11
-rw-r--r--sys/kern/tty_info.c4
-rw-r--r--sys/kern/uipc_mqueue.c2
-rw-r--r--sys/kern/uipc_syscalls.c12
-rw-r--r--sys/kern/vfs_bio.c2
-rw-r--r--sys/mips/include/cpu.h1
-rw-r--r--sys/netgraph/ng_pptpgre.c377
-rw-r--r--sys/netgraph/ng_pptpgre.h6
-rw-r--r--sys/netinet/sctp_output.c4
-rw-r--r--sys/powerpc/include/atomic.h2
-rw-r--r--sys/powerpc/include/cpu.h1
-rw-r--r--sys/powerpc/powerpc/mp_machdep.c6
-rw-r--r--sys/riscv/include/cpu.h1
-rw-r--r--sys/riscv/riscv/pmap.c13
-rw-r--r--sys/sparc64/include/cpu.h1
-rw-r--r--sys/sys/capability.h3
-rw-r--r--sys/sys/socketvar.h3
-rw-r--r--sys/sys/syscallsubr.h2
-rw-r--r--sys/sys/sysproto.h46
-rw-r--r--sys/sys/tty.h8
-rw-r--r--sys/vm/vm_kern.c4
-rw-r--r--sys/vm/vm_pageout.c2
-rw-r--r--sys/x86/x86/delay.c67
62 files changed, 2606 insertions, 328 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index f74db37a283e..34fb1e8e4370 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -100,6 +100,8 @@ options WITNESS # Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
options VERBOSE_SYSINIT=0 # Support debug.verbose_sysinit, off by default
+# Warning: KUBSAN can result in a kernel too large for loader to load
+#options KUBSAN # Kernel Undefined Behavior Sanitizer
# Kernel dump features.
options EKCD # Support for encrypted kernel dumps
diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h
index db3554fad84f..1b8a552d3e7c 100644
--- a/sys/amd64/include/cpu.h
+++ b/sys/amd64/include/cpu.h
@@ -77,6 +77,7 @@ extern char etext[];
extern void (*vmm_resume_p)(void);
void cpu_halt(void);
+void cpu_lock_delay(void);
void cpu_reset(void);
void fork_trampoline(void);
void swi_vm(void *);
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 66d441e96c68..bcaa0cd45459 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -32,6 +32,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "opt_compat.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -1071,7 +1073,7 @@ linux_elf_modevent(module_t mod, int type, void *data)
error = EINVAL;
if (error == 0) {
SET_FOREACH(lihp, linux_ioctl_handler_set)
- linux_ioctl_register_handler(*lihp);
+ linux32_ioctl_register_handler(*lihp);
LIST_INIT(&futex_list);
mtx_init(&futex_mtx, "ftllk", NULL, MTX_DEF);
stclohz = (stathz ? stathz : hz);
@@ -1093,7 +1095,7 @@ linux_elf_modevent(module_t mod, int type, void *data)
}
if (error == 0) {
SET_FOREACH(lihp, linux_ioctl_handler_set)
- linux_ioctl_unregister_handler(*lihp);
+ linux32_ioctl_unregister_handler(*lihp);
mtx_destroy(&futex_mtx);
if (bootverbose)
printf("Linux ELF exec handler removed\n");
diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h
index 1ef5798ecddb..7c7de38a2536 100644
--- a/sys/arm/include/cpu.h
+++ b/sys/arm/include/cpu.h
@@ -61,6 +61,7 @@ get_cyclecount(void)
#define cpu_getstack(td) ((td)->td_frame->tf_usr_sp)
#define cpu_setstack(td, sp) ((td)->td_frame->tf_usr_sp = (sp))
#define cpu_spinwait() /* nothing */
+#define cpu_lock_delay() DELAY(1)
#define ARM_NVEC 8
#define ARM_VEC_ALL 0xffffffff
diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h
index 7424b45e78f4..28fc14e3dae3 100644
--- a/sys/arm/include/elf.h
+++ b/sys/arm/include/elf.h
@@ -84,7 +84,7 @@ __ElfType(Auxinfo);
*/
#define MAGIC_TRAMP_NUMBER 0x5c000003
-#define ET_DYN_LOAD_ADDR 0x12000
+#define ET_DYN_LOAD_ADDR 0x500000
/* Flags passed in AT_HWCAP. */
#define HWCAP_SWP 0x00000001 /* Unsupported, never set. */
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index ee4ab292928f..c626727d5209 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -92,6 +92,8 @@ options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
options ALT_BREAK_TO_DEBUGGER # Enter debugger on keyboard escape sequence
options USB_DEBUG # enable debug msgs
options VERBOSE_SYSINIT=0 # Support debug.verbose_sysinit, off by default
+# Warning: KUBSAN can result in a kernel too large for loader to load
+#options KUBSAN # Kernel Undefined Behavior Sanitizer
# Kernel dump features.
options EKCD # Support for encrypted kernel dumps
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index f5d7909b7899..3cfc59c25bff 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -51,6 +51,7 @@
#define cpu_getstack(td) ((td)->td_frame->tf_sp)
#define cpu_setstack(td, sp) ((td)->td_frame->tf_sp = (sp))
#define cpu_spinwait() __asm __volatile("yield" ::: "memory")
+#define cpu_lock_delay() DELAY(1)
/* Extract CPU affinity levels 0-3 */
#define CPU_AFF0(mpidr) (u_int)(((mpidr) >> 0) & 0xff)
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 2483c5e7633e..a1ac49d146db 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -2005,7 +2005,7 @@ daasync(void *callback_arg, u_int32_t code,
periph = (struct cam_periph *)callback_arg;
switch (code) {
- case AC_FOUND_DEVICE:
+ case AC_FOUND_DEVICE: /* callback to create periph, no locking yet */
{
struct ccb_getdev *cgd;
cam_status status;
@@ -2041,7 +2041,7 @@ daasync(void *callback_arg, u_int32_t code,
"due to status 0x%x\n", status);
return;
}
- case AC_ADVINFO_CHANGED:
+ case AC_ADVINFO_CHANGED: /* Doesn't touch periph */
{
uintptr_t buftype;
@@ -2064,8 +2064,10 @@ daasync(void *callback_arg, u_int32_t code,
ccb = (union ccb *)arg;
/*
- * Handle all UNIT ATTENTIONs except our own,
- * as they will be handled by daerror().
+ * Handle all UNIT ATTENTIONs except our own, as they will be
+ * handled by daerror(). Since this comes from a different periph,
+ * that periph's lock is held, not ours, so we have to take it ours
+ * out to touch softc flags.
*/
if (xpt_path_periph(ccb->ccb_h.path) != periph &&
scsi_extract_sense_ccb(ccb,
@@ -2093,9 +2095,13 @@ daasync(void *callback_arg, u_int32_t code,
}
break;
}
- case AC_SCSI_AEN:
+ case AC_SCSI_AEN: /* Called for this path: periph locked */
+ /*
+ * Appears to be currently unused for SCSI devices, only ata SIMs
+ * generate this.
+ */
+ cam_periph_assert(periph, MA_OWNED);
softc = (struct da_softc *)periph->softc;
- cam_periph_lock(periph);
if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) &&
(softc->flags & DA_FLAG_TUR_PENDING) == 0) {
if (da_periph_acquire(periph, DA_REF_TUR) == 0) {
@@ -2103,31 +2109,28 @@ daasync(void *callback_arg, u_int32_t code,
daschedule(periph);
}
}
- cam_periph_unlock(periph);
/* FALLTHROUGH */
- case AC_SENT_BDR:
- case AC_BUS_RESET:
+ case AC_SENT_BDR: /* Called for this path: periph locked */
+ case AC_BUS_RESET: /* Called for this path: periph locked */
{
struct ccb_hdr *ccbh;
+ cam_periph_assert(periph, MA_OWNED);
softc = (struct da_softc *)periph->softc;
/*
* Don't fail on the expected unit attention
* that will occur.
*/
- cam_periph_lock(periph);
softc->flags |= DA_FLAG_RETRY_UA;
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
ccbh->ccb_state |= DA_CCB_RETRY_UA;
- cam_periph_unlock(periph);
break;
}
- case AC_INQ_CHANGED:
- cam_periph_lock(periph);
+ case AC_INQ_CHANGED: /* Called for this path: periph locked */
+ cam_periph_assert(periph, MA_OWNED);
softc = (struct da_softc *)periph->softc;
softc->flags &= ~DA_FLAG_PROBED;
dareprobe(periph);
- cam_periph_unlock(periph);
break;
default:
break;
diff --git a/sys/compat/freebsd32/capabilities.conf b/sys/compat/freebsd32/capabilities.conf
index c96dab7aa9d4..8d7105cef948 100644
--- a/sys/compat/freebsd32/capabilities.conf
+++ b/sys/compat/freebsd32/capabilities.conf
@@ -203,6 +203,7 @@ pdkill
freebsd32_pipe
pipe2
poll
+freebsd32_ppoll
freebsd32_posix_fallocate
freebsd32_pread
freebsd32_preadv
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
index ed48baf7295f..9f15277fc77c 100644
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -55,10 +55,10 @@ struct freebsd32_sendmsg_args {
};
struct freebsd32_recvfrom_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char buf_l_[PADL_(uint32_t)]; uint32_t buf; char buf_r_[PADR_(uint32_t)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
char len_l_[PADL_(uint32_t)]; uint32_t len; char len_r_[PADR_(uint32_t)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
- char from_l_[PADL_(uint32_t)]; uint32_t from; char from_r_[PADR_(uint32_t)];
+ char from_l_[PADL_(struct sockaddr *)]; struct sockaddr * from; char from_r_[PADR_(struct sockaddr *)];
char fromlenaddr_l_[PADL_(uint32_t)]; uint32_t fromlenaddr; char fromlenaddr_r_[PADR_(uint32_t)];
};
struct freebsd10_freebsd32_pipe_args {
@@ -417,7 +417,7 @@ struct freebsd32_pwrite_args {
char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
};
struct freebsd32_mmap_args {
- char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
@@ -461,7 +461,7 @@ struct freebsd32_pwrite_args {
char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
};
struct freebsd32_mmap_args {
- char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
@@ -1020,7 +1020,7 @@ struct freebsd6_freebsd32_pwrite_args {
char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
};
struct freebsd6_freebsd32_mmap_args {
- char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index 1a6ff314dfa2..de97d29af51e 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -624,7 +624,7 @@ struct sysent freebsd32_sysent[] = {
#else
{ AS(freebsd32_procctl_args), (sy_call_t *)freebsd32_procctl, AUE_PROCCTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 544 = freebsd32_procctl */
#endif
- { AS(freebsd32_ppoll_args), (sy_call_t *)freebsd32_ppoll, AUE_POLL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 545 = freebsd32_ppoll */
+ { AS(freebsd32_ppoll_args), (sy_call_t *)freebsd32_ppoll, AUE_POLL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 545 = freebsd32_ppoll */
{ AS(freebsd32_futimens_args), (sy_call_t *)freebsd32_futimens, AUE_FUTIMES, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 546 = freebsd32_futimens */
{ AS(freebsd32_utimensat_args), (sy_call_t *)freebsd32_utimensat, AUE_FUTIMESAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 547 = freebsd32_utimensat */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 548 = obsolete numa_getaffinity */
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
index 59d97c7a74ce..116d6c40716d 100644
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -139,7 +139,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
uarg[0] = (intptr_t) p->type; /* const char * */
uarg[1] = (intptr_t) p->path; /* const char * */
iarg[2] = p->flags; /* int */
- uarg[3] = (intptr_t) p->data; /* caddr_t */
+ uarg[3] = (intptr_t) p->data; /* void * */
*n_args = 4;
break;
}
@@ -200,10 +200,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 29: {
struct freebsd32_recvfrom_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = p->buf; /* uint32_t */
+ uarg[1] = (intptr_t) p->buf; /* void * */
uarg[2] = p->len; /* uint32_t */
iarg[3] = p->flags; /* int */
- uarg[4] = p->from; /* uint32_t */
+ uarg[4] = (intptr_t) p->from; /* struct sockaddr * */
uarg[5] = p->fromlenaddr; /* uint32_t */
*n_args = 6;
break;
@@ -212,7 +212,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 30: {
struct accept_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->name; /* caddr_t */
+ uarg[1] = (intptr_t) p->name; /* struct sockaddr * */
uarg[2] = (intptr_t) p->anamelen; /* int * */
*n_args = 3;
break;
@@ -221,7 +221,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 31: {
struct getpeername_args *p = params;
iarg[0] = p->fdes; /* int */
- uarg[1] = (intptr_t) p->asa; /* caddr_t */
+ uarg[1] = (intptr_t) p->asa; /* struct sockaddr * */
uarg[2] = (intptr_t) p->alen; /* int * */
*n_args = 3;
break;
@@ -230,7 +230,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 32: {
struct getsockname_args *p = params;
iarg[0] = p->fdes; /* int */
- uarg[1] = (intptr_t) p->asa; /* caddr_t */
+ uarg[1] = (intptr_t) p->asa; /* struct sockaddr * */
uarg[2] = (intptr_t) p->alen; /* int * */
*n_args = 3;
break;
@@ -292,7 +292,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* profil */
case 44: {
struct profil_args *p = params;
- uarg[0] = (intptr_t) p->samples; /* caddr_t */
+ uarg[0] = (intptr_t) p->samples; /* char * */
uarg[1] = p->size; /* size_t */
uarg[2] = p->offset; /* size_t */
uarg[3] = p->scale; /* u_int */
@@ -585,7 +585,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 98: {
struct connect_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->name; /* caddr_t */
+ uarg[1] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[2] = p->namelen; /* int */
*n_args = 3;
break;
@@ -602,7 +602,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 104: {
struct bind_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->name; /* caddr_t */
+ uarg[1] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[2] = p->namelen; /* int */
*n_args = 3;
break;
@@ -613,7 +613,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->s; /* int */
iarg[1] = p->level; /* int */
iarg[2] = p->name; /* int */
- uarg[3] = (intptr_t) p->val; /* caddr_t */
+ uarg[3] = (intptr_t) p->val; /* const void * */
iarg[4] = p->valsize; /* int */
*n_args = 5;
break;
@@ -648,7 +648,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->s; /* int */
iarg[1] = p->level; /* int */
iarg[2] = p->name; /* int */
- uarg[3] = (intptr_t) p->val; /* caddr_t */
+ uarg[3] = (intptr_t) p->val; /* void * */
uarg[4] = (intptr_t) p->avalsize; /* int * */
*n_args = 5;
break;
@@ -740,10 +740,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 133: {
struct sendto_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->buf; /* caddr_t */
+ uarg[1] = (intptr_t) p->buf; /* const void * */
uarg[2] = p->len; /* size_t */
iarg[3] = p->flags; /* int */
- uarg[4] = (intptr_t) p->to; /* caddr_t */
+ uarg[4] = (intptr_t) p->to; /* const struct sockaddr * */
iarg[5] = p->tolen; /* int */
*n_args = 6;
break;
@@ -808,7 +808,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
uarg[0] = (intptr_t) p->path; /* const char * */
iarg[1] = p->cmd; /* int */
iarg[2] = p->uid; /* int */
- uarg[3] = (intptr_t) p->arg; /* caddr_t */
+ uarg[3] = (intptr_t) p->arg; /* void * */
*n_args = 4;
break;
}
@@ -2312,9 +2312,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 472: {
struct sctp_generic_sendmsg_args *p = params;
iarg[0] = p->sd; /* int */
- uarg[1] = (intptr_t) p->msg; /* caddr_t */
+ uarg[1] = (intptr_t) p->msg; /* void * */
iarg[2] = p->mlen; /* int */
- uarg[3] = (intptr_t) p->to; /* caddr_t */
+ uarg[3] = (intptr_t) p->to; /* struct sockaddr * */
iarg[4] = p->tolen; /* __socklen_t */
uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
iarg[6] = p->flags; /* int */
@@ -2327,7 +2327,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->sd; /* int */
uarg[1] = (intptr_t) p->iov; /* struct iovec * */
iarg[2] = p->iovlen; /* int */
- uarg[3] = (intptr_t) p->to; /* caddr_t */
+ uarg[3] = (intptr_t) p->to; /* struct sockaddr * */
iarg[4] = p->tolen; /* __socklen_t */
uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
iarg[6] = p->flags; /* int */
@@ -2375,7 +2375,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* freebsd32_mmap */
case 477: {
struct freebsd32_mmap_args *p = params;
- uarg[0] = (intptr_t) p->addr; /* caddr_t */
+ uarg[0] = (intptr_t) p->addr; /* void * */
uarg[1] = p->len; /* size_t */
iarg[2] = p->prot; /* int */
iarg[3] = p->flags; /* int */
@@ -2443,7 +2443,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* freebsd32_mmap */
case 477: {
struct freebsd32_mmap_args *p = params;
- uarg[0] = (intptr_t) p->addr; /* caddr_t */
+ uarg[0] = (intptr_t) p->addr; /* void * */
uarg[1] = p->len; /* size_t */
iarg[2] = p->prot; /* int */
iarg[3] = p->flags; /* int */
@@ -3021,7 +3021,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct bindat_args *p = params;
iarg[0] = p->fd; /* int */
iarg[1] = p->s; /* int */
- uarg[2] = (intptr_t) p->name; /* caddr_t */
+ uarg[2] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[3] = p->namelen; /* int */
*n_args = 4;
break;
@@ -3031,7 +3031,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct connectat_args *p = params;
iarg[0] = p->fd; /* int */
iarg[1] = p->s; /* int */
- uarg[2] = (intptr_t) p->name; /* caddr_t */
+ uarg[2] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[3] = p->namelen; /* int */
*n_args = 4;
break;
@@ -3462,7 +3462,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland void *";
break;
default:
break;
@@ -3555,7 +3555,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "uint32_t";
+ p = "userland void *";
break;
case 2:
p = "uint32_t";
@@ -3564,7 +3564,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 4:
- p = "uint32_t";
+ p = "userland struct sockaddr *";
break;
case 5:
p = "uint32_t";
@@ -3580,7 +3580,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 2:
p = "userland int *";
@@ -3596,7 +3596,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 2:
p = "userland int *";
@@ -3612,7 +3612,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 2:
p = "userland int *";
@@ -3696,7 +3696,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 44:
switch(ndx) {
case 0:
- p = "caddr_t";
+ p = "userland char *";
break;
case 1:
p = "size_t";
@@ -4164,7 +4164,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 2:
p = "int";
@@ -4193,7 +4193,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 2:
p = "int";
@@ -4215,7 +4215,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland const void *";
break;
case 4:
p = "int";
@@ -4276,7 +4276,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland void *";
break;
case 4:
p = "userland int *";
@@ -4431,7 +4431,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland const void *";
break;
case 2:
p = "size_t";
@@ -4440,7 +4440,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 4:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 5:
p = "int";
@@ -4546,7 +4546,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland void *";
break;
default:
break;
@@ -6996,13 +6996,13 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland void *";
break;
case 2:
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 4:
p = "__socklen_t";
@@ -7030,7 +7030,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 4:
p = "__socklen_t";
@@ -7128,7 +7128,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 477:
switch(ndx) {
case 0:
- p = "caddr_t";
+ p = "userland void *";
break;
case 1:
p = "size_t";
@@ -7264,7 +7264,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 477:
switch(ndx) {
case 0:
- p = "caddr_t";
+ p = "userland void *";
break;
case 1:
p = "size_t";
@@ -8323,7 +8323,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 2:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 3:
p = "int";
@@ -8342,7 +8342,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 2:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 3:
p = "int";
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 36d2d65fa3ce..980c4194f184 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -97,7 +97,7 @@
20 AUE_GETPID NOPROTO { pid_t getpid(void); }
21 AUE_MOUNT NOPROTO { int mount(const char *type, \
const char *path, \
- int flags, caddr_t data); }
+ int flags, void *data); }
22 AUE_UMOUNT NOPROTO { int unmount(const char *path, int flags); }
23 AUE_SETUID NOPROTO { int setuid(uid_t uid); }
24 AUE_GETUID NOPROTO { uid_t getuid(void); }
@@ -108,14 +108,17 @@
int flags); }
28 AUE_SENDMSG STD { int freebsd32_sendmsg(int s, struct msghdr32 *msg, \
int flags); }
-29 AUE_RECVFROM STD { int freebsd32_recvfrom(int s, uint32_t buf, \
- uint32_t len, int flags, uint32_t from, \
+29 AUE_RECVFROM STD { int freebsd32_recvfrom(int s, void *buf, \
+ uint32_t len, int flags, \
+ struct sockaddr *from, \
uint32_t fromlenaddr); }
-30 AUE_ACCEPT NOPROTO { int accept(int s, caddr_t name, \
+30 AUE_ACCEPT NOPROTO { int accept(int s, struct sockaddr *name, \
int *anamelen); }
-31 AUE_GETPEERNAME NOPROTO { int getpeername(int fdes, caddr_t asa, \
+31 AUE_GETPEERNAME NOPROTO { int getpeername(int fdes, \
+ struct sockaddr *asa, \
int *alen); }
-32 AUE_GETSOCKNAME NOPROTO { int getsockname(int fdes, caddr_t asa, \
+32 AUE_GETSOCKNAME NOPROTO { int getsockname(int fdes, \
+ struct sockaddr *asa, \
int *alen); }
33 AUE_ACCESS NOPROTO { int access(const char *path, int amode); }
34 AUE_CHFLAGS NOPROTO { int chflags(const char *path, u_long flags); }
@@ -130,7 +133,7 @@
41 AUE_DUP NOPROTO { int dup(u_int fd); }
42 AUE_PIPE COMPAT10 { int freebsd32_pipe(void); }
43 AUE_GETEGID NOPROTO { gid_t getegid(void); }
-44 AUE_PROFILE NOPROTO { int profil(caddr_t samples, size_t size, \
+44 AUE_PROFILE NOPROTO { int profil(char *samples, size_t size, \
size_t offset, u_int scale); }
45 AUE_KTRACE NOPROTO { int ktrace(const char *fname, int ops, \
int facs, int pid); }
@@ -214,7 +217,8 @@
int prio); }
97 AUE_SOCKET NOPROTO { int socket(int domain, int type, \
int protocol); }
-98 AUE_CONNECT NOPROTO { int connect(int s, caddr_t name, \
+98 AUE_CONNECT NOPROTO { int connect(int s, \
+ const struct sockaddr *name, \
int namelen); }
99 AUE_NULL OBSOL oaccept
100 AUE_GETPRIORITY NOPROTO { int getpriority(int which, int who); }
@@ -222,10 +226,10 @@
102 AUE_NULL OBSOL orecv
103 AUE_SIGRETURN COMPAT { int freebsd32_sigreturn( \
struct ia32_sigcontext3 *sigcntxp); }
-104 AUE_BIND NOPROTO { int bind(int s, caddr_t name, \
+104 AUE_BIND NOPROTO { int bind(int s, const struct sockaddr *name, \
int namelen); }
105 AUE_SETSOCKOPT NOPROTO { int setsockopt(int s, int level, \
- int name, caddr_t val, int valsize); }
+ int name, const void *val, int valsize); }
106 AUE_LISTEN NOPROTO { int listen(int s, int backlog); }
107 AUE_NULL OBSOL vtimes
108 AUE_O_SIGVEC COMPAT { int freebsd32_sigvec(int signum, \
@@ -246,7 +250,7 @@
117 AUE_GETRUSAGE STD { int freebsd32_getrusage(int who, \
struct rusage32 *rusage); }
118 AUE_GETSOCKOPT NOPROTO { int getsockopt(int s, int level, \
- int name, caddr_t val, int *avalsize); }
+ int name, void *val, int *avalsize); }
119 AUE_NULL UNIMPL resuba (BSD/OS 2.x)
120 AUE_READV STD { int freebsd32_readv(int fd, \
struct iovec32 *iovp, u_int iovcnt); }
@@ -267,8 +271,9 @@
130 AUE_FTRUNCATE COMPAT|NOPROTO { int ftruncate(int fd, int length); }
131 AUE_FLOCK NOPROTO { int flock(int fd, int how); }
132 AUE_MKFIFO NOPROTO { int mkfifo(const char *path, mode_t mode); }
-133 AUE_SENDTO NOPROTO { int sendto(int s, caddr_t buf, \
- size_t len, int flags, caddr_t to, \
+133 AUE_SENDTO NOPROTO { int sendto(int s, const void *buf, \
+ size_t len, int flags, \
+ const struct sockaddr *to, \
int tolen); }
134 AUE_SHUTDOWN NOPROTO { int shutdown(int s, int how); }
135 AUE_SOCKETPAIR NOPROTO { int socketpair(int domain, int type, \
@@ -289,7 +294,7 @@
146 AUE_KILLPG OBSOL killpg
147 AUE_SETSID NOPROTO { int setsid(void); }
148 AUE_QUOTACTL NOPROTO { int quotactl(const char *path, int cmd, \
- int uid, caddr_t arg); }
+ int uid, void *arg); }
149 AUE_O_QUOTA OBSOL oquota
150 AUE_GETSOCKNAME OBSOL ogetsockname
@@ -368,7 +373,7 @@
__setrlimit_args int
196 AUE_GETDIRENTRIES COMPAT11 { int freebsd32_getdirentries(int fd, \
char *buf, u_int count, int32_t *basep); }
-197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(caddr_t addr, \
+197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(void *addr, \
size_t len, int prot, int flags, int fd, \
int pad, uint32_t pos1, uint32_t pos2); }
198 AUE_NULL NOPROTO { int nosys(void); } __syscall \
@@ -852,11 +857,12 @@
469 AUE_NULL UNIMPL __getpath_fromfd
470 AUE_NULL UNIMPL __getpath_fromaddr
471 AUE_SCTP_PEELOFF NOPROTO|NOSTD { int sctp_peeloff(int sd, uint32_t name); }
-472 AUE_SCTP_GENERIC_SENDMSG NOPROTO|NOSTD { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
- caddr_t to, __socklen_t tolen, \
+472 AUE_SCTP_GENERIC_SENDMSG NOPROTO|NOSTD { int sctp_generic_sendmsg( \
+ int sd, void *msg, int mlen, \
+ struct sockaddr *to, __socklen_t tolen, \
struct sctp_sndrcvinfo *sinfo, int flags); }
473 AUE_SCTP_GENERIC_SENDMSG_IOV NOPROTO|NOSTD { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
- caddr_t to, __socklen_t tolen, \
+ struct sockaddr *to, __socklen_t tolen, \
struct sctp_sndrcvinfo *sinfo, int flags); }
474 AUE_SCTP_GENERIC_RECVMSG NOPROTO|NOSTD { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
struct sockaddr * from, __socklen_t *fromlenaddr, \
@@ -870,7 +876,7 @@
const void *buf, size_t nbyte, \
int pad, \
uint32_t offset1, uint32_t offset2); }
-477 AUE_MMAP STD { caddr_t freebsd32_mmap(caddr_t addr, \
+477 AUE_MMAP STD { caddr_t freebsd32_mmap(void *addr, \
size_t len, int prot, int flags, int fd, \
int pad, \
uint32_t pos1, uint32_t pos2); }
@@ -891,7 +897,7 @@
476 AUE_PWRITE STD { ssize_t freebsd32_pwrite(int fd, \
const void *buf, size_t nbyte, \
uint32_t offset1, uint32_t offset2); }
-477 AUE_MMAP STD { caddr_t freebsd32_mmap(caddr_t addr, \
+477 AUE_MMAP STD { caddr_t freebsd32_mmap(void *addr, \
size_t len, int prot, int flags, int fd, \
uint32_t pos1, uint32_t pos2); }
478 AUE_LSEEK STD { off_t freebsd32_lseek(int fd, \
@@ -1054,9 +1060,11 @@
uint32_t fcntlrights); }
537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \
uint32_t *fcntlrightsp); }
-538 AUE_BINDAT NOPROTO { int bindat(int fd, int s, caddr_t name, \
+538 AUE_BINDAT NOPROTO { int bindat(int fd, int s, \
+ const struct sockaddr *name, \
int namelen); }
-539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, caddr_t name, \
+539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, \
+ const struct sockaddr *name, \
int namelen); }
540 AUE_CHFLAGSAT NOPROTO { int chflagsat(int fd, const char *path, \
u_long flags, int atflag); }
diff --git a/sys/compat/linux/linux_common.c b/sys/compat/linux/linux_common.c
index b9e35311bdfe..551823d7e0de 100644
--- a/sys/compat/linux/linux_common.c
+++ b/sys/compat/linux/linux_common.c
@@ -35,9 +35,11 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/eventhandler.h>
+#include <sys/sx.h>
#include <sys/sysctl.h>
#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_util.h>
@@ -48,6 +50,11 @@ MODULE_VERSION(linux_common, 1);
SET_DECLARE(linux_device_handler_set, struct linux_device_handler);
+TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers =
+ TAILQ_HEAD_INITIALIZER(linux_ioctl_handlers);
+struct sx linux_ioctl_sx;
+SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "Linux ioctl handlers");
+
static eventhandler_tag linux_exec_tag;
static eventhandler_tag linux_thread_dtor_tag;
static eventhandler_tag linux_exit_tag;
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index cea8721f096e..0a8e5087984b 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -161,17 +161,19 @@ DATA_SET(linux_ioctl_handler_set, video2_handler);
DATA_SET(linux_ioctl_handler_set, fbsd_usb);
DATA_SET(linux_ioctl_handler_set, evdev_handler);
-struct handler_element
-{
- TAILQ_ENTRY(handler_element) list;
- int (*func)(struct thread *, struct linux_ioctl_args *);
- int low, high, span;
-};
-
-static TAILQ_HEAD(, handler_element) handlers =
- TAILQ_HEAD_INITIALIZER(handlers);
+#ifdef __i386__
+static TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers =
+ TAILQ_HEAD_INITIALIZER(linux_ioctl_handlers);
static struct sx linux_ioctl_sx;
SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "Linux ioctl handlers");
+#else
+extern TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers;
+extern struct sx linux_ioctl_sx;
+#endif
+#ifdef COMPAT_LINUX32
+static TAILQ_HEAD(, linux_ioctl_handler_element) linux32_ioctl_handlers =
+ TAILQ_HEAD_INITIALIZER(linux32_ioctl_handlers);
+#endif
/*
* hdio related ioctls for VMWare support
@@ -3684,7 +3686,7 @@ int
linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
{
struct file *fp;
- struct handler_element *he;
+ struct linux_ioctl_handler_element *he;
int error, cmd;
#ifdef DEBUG
@@ -3705,7 +3707,20 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
cmd = args->cmd & 0xffff;
sx_slock(&linux_ioctl_sx);
mtx_lock(&Giant);
- TAILQ_FOREACH(he, &handlers, list) {
+#ifdef COMPAT_LINUX32
+ TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
+ if (cmd >= he->low && cmd <= he->high) {
+ error = (*he->func)(td, args);
+ if (error != ENOIOCTL) {
+ mtx_unlock(&Giant);
+ sx_sunlock(&linux_ioctl_sx);
+ fdrop(fp, td);
+ return (error);
+ }
+ }
+ }
+#endif
+ TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
if (cmd >= he->low && cmd <= he->high) {
error = (*he->func)(td, args);
if (error != ENOIOCTL) {
@@ -3737,7 +3752,7 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
int
linux_ioctl_register_handler(struct linux_ioctl_handler *h)
{
- struct handler_element *he, *cur;
+ struct linux_ioctl_handler_element *he, *cur;
if (h == NULL || h->func == NULL)
return (EINVAL);
@@ -3747,7 +3762,7 @@ linux_ioctl_register_handler(struct linux_ioctl_handler *h)
* create a new element.
*/
sx_xlock(&linux_ioctl_sx);
- TAILQ_FOREACH(he, &handlers, list) {
+ TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
if (he->func == h->func)
break;
}
@@ -3756,7 +3771,7 @@ linux_ioctl_register_handler(struct linux_ioctl_handler *h)
M_LINUX, M_WAITOK);
he->func = h->func;
} else
- TAILQ_REMOVE(&handlers, he, list);
+ TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
/* Initialize range information. */
he->low = h->low;
@@ -3764,14 +3779,14 @@ linux_ioctl_register_handler(struct linux_ioctl_handler *h)
he->span = h->high - h->low + 1;
/* Add the element to the list, sorted on span. */
- TAILQ_FOREACH(cur, &handlers, list) {
+ TAILQ_FOREACH(cur, &linux_ioctl_handlers, list) {
if (cur->span > he->span) {
TAILQ_INSERT_BEFORE(cur, he, list);
sx_xunlock(&linux_ioctl_sx);
return (0);
}
}
- TAILQ_INSERT_TAIL(&handlers, he, list);
+ TAILQ_INSERT_TAIL(&linux_ioctl_handlers, he, list);
sx_xunlock(&linux_ioctl_sx);
return (0);
@@ -3780,15 +3795,80 @@ linux_ioctl_register_handler(struct linux_ioctl_handler *h)
int
linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
{
- struct handler_element *he;
+ struct linux_ioctl_handler_element *he;
+
+ if (h == NULL || h->func == NULL)
+ return (EINVAL);
+
+ sx_xlock(&linux_ioctl_sx);
+ TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
+ if (he->func == h->func) {
+ TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
+ sx_xunlock(&linux_ioctl_sx);
+ free(he, M_LINUX);
+ return (0);
+ }
+ }
+ sx_xunlock(&linux_ioctl_sx);
+
+ return (EINVAL);
+}
+
+#ifdef COMPAT_LINUX32
+int
+linux32_ioctl_register_handler(struct linux_ioctl_handler *h)
+{
+ struct linux_ioctl_handler_element *he, *cur;
if (h == NULL || h->func == NULL)
return (EINVAL);
+ /*
+ * Reuse the element if the handler is already on the list, otherwise
+ * create a new element.
+ */
sx_xlock(&linux_ioctl_sx);
- TAILQ_FOREACH(he, &handlers, list) {
+ TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
+ if (he->func == h->func)
+ break;
+ }
+ if (he == NULL) {
+ he = malloc(sizeof(*he), M_LINUX, M_WAITOK);
+ he->func = h->func;
+ } else
+ TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
+
+ /* Initialize range information. */
+ he->low = h->low;
+ he->high = h->high;
+ he->span = h->high - h->low + 1;
+
+ /* Add the element to the list, sorted on span. */
+ TAILQ_FOREACH(cur, &linux32_ioctl_handlers, list) {
+ if (cur->span > he->span) {
+ TAILQ_INSERT_BEFORE(cur, he, list);
+ sx_xunlock(&linux_ioctl_sx);
+ return (0);
+ }
+ }
+ TAILQ_INSERT_TAIL(&linux32_ioctl_handlers, he, list);
+ sx_xunlock(&linux_ioctl_sx);
+
+ return (0);
+}
+
+int
+linux32_ioctl_unregister_handler(struct linux_ioctl_handler *h)
+{
+ struct linux_ioctl_handler_element *he;
+
+ if (h == NULL || h->func == NULL)
+ return (EINVAL);
+
+ sx_xlock(&linux_ioctl_sx);
+ TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
if (he->func == h->func) {
- TAILQ_REMOVE(&handlers, he, list);
+ TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
sx_xunlock(&linux_ioctl_sx);
free(he, M_LINUX);
return (0);
@@ -3798,3 +3878,4 @@ linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
return (EINVAL);
}
+#endif
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
index d8aaadd62ddd..519f55e6c161 100644
--- a/sys/compat/linux/linux_ioctl.h
+++ b/sys/compat/linux/linux_ioctl.h
@@ -770,7 +770,18 @@ struct linux_ioctl_handler {
int low, high;
};
+struct linux_ioctl_handler_element
+{
+ TAILQ_ENTRY(linux_ioctl_handler_element) list;
+ int (*func)(struct thread *, struct linux_ioctl_args *);
+ int low, high, span;
+};
+
int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
+#ifdef COMPAT_LINUX32
+int linux32_ioctl_register_handler(struct linux_ioctl_handler *h);
+int linux32_ioctl_unregister_handler(struct linux_ioctl_handler *h);
+#endif
#endif /* !_LINUX_IOCTL_H_ */
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 415bc1024252..15a137a5dd73 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -1520,7 +1520,7 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
int s;
int level;
int name;
- caddr_t val;
+ const void *val;
int valsize;
} */ bsd_args;
l_timeval linux_tv;
@@ -1570,10 +1570,11 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
bsd_args.valsize = args->optlen;
if (name == IPV6_NEXTHOP) {
- linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.val,
- bsd_args.valsize);
+ linux_to_bsd_sockaddr(__DECONST(struct sockaddr *,
+ bsd_args.val), bsd_args.valsize);
error = sys_setsockopt(td, &bsd_args);
- bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
+ bsd_to_linux_sockaddr(__DECONST(struct sockaddr *,
+ bsd_args.val));
} else
error = sys_setsockopt(td, &bsd_args);
diff --git a/sys/conf/files b/sys/conf/files
index 1ca735ba9957..9294d67aa172 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3824,6 +3824,7 @@ kern/kern_thread.c standard
kern/kern_time.c standard
kern/kern_timeout.c standard
kern/kern_tslog.c optional tslog
+kern/kern_ubsan.c optional kubsan
kern/kern_umtx.c standard
kern/kern_uuid.c standard
kern/kern_xxx.c standard
diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk
index 98d179446905..398dc7165984 100644
--- a/sys/conf/kern.post.mk
+++ b/sys/conf/kern.post.mk
@@ -28,6 +28,10 @@ MKMODULESENV+= WITH_CTF="${WITH_CTF}"
MKMODULESENV+= WITH_EXTRA_TCP_STACKS="${WITH_EXTRA_TCP_STACKS}"
.endif
+.if defined(SAN_CFLAGS)
+MKMODULESENV+= SAN_CFLAGS="${SAN_CFLAGS}"
+.endif
+
# Allow overriding the kernel debug directory, so kernel and user debug may be
# installed in different directories. Setting it to "" restores the historical
# behavior of installing debug files in the kernel directory.
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 38a9c14ddbb5..bca9ff79e756 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -113,6 +113,12 @@ PROF= -pg
.endif
DEFINED_PROF= ${PROF}
+KUBSAN_ENABLED!= grep KUBSAN opt_global.h || true ; echo
+.if !empty(KUBSAN_ENABLED)
+SAN_CFLAGS+= -fsanitize=undefined
+.endif
+CFLAGS+= ${SAN_CFLAGS}
+
# Put configuration-specific C flags last (except for ${PROF}) so that they
# can override the others.
CFLAGS+= ${CONF_CFLAGS}
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index a357c565ab5f..4f239d10bd3a 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -377,6 +377,9 @@ ${_src}:
.endfor
.endif
+# Add the sanitizer C flags
+CFLAGS+= ${SAN_CFLAGS}
+
# Respect configuration-specific C flags.
CFLAGS+= ${ARCH_FLAGS} ${CONF_CFLAGS}
diff --git a/sys/conf/options b/sys/conf/options
index 9d86cbdfd663..240b1d606df5 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -232,6 +232,9 @@ UMTX_CHAINS opt_global.h
VERBOSE_SYSINIT
ZSTDIO opt_zstdio.h
+# Sanitizers
+KUBSAN opt_global.h
+
# POSIX kernel options
P1003_1B_MQUEUE opt_posix.h
P1003_1B_SEMAPHORES opt_posix.h
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index dbebe5b0ece7..52734ed98246 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -574,6 +574,7 @@ struct sge_txq {
uint64_t txpkts1_wrs; /* # of type1 coalesced tx work requests */
uint64_t txpkts0_pkts; /* # of frames in type0 coalesced tx WRs */
uint64_t txpkts1_pkts; /* # of frames in type1 coalesced tx WRs */
+ uint64_t raw_wrs; /* # of raw work requests (alloc_wr_mbuf) */
/* stats for not-that-common events */
} __aligned(CACHE_LINE_SIZE);
@@ -1170,6 +1171,7 @@ void t4_intr_err(void *);
void t4_intr_evt(void *);
void t4_wrq_tx_locked(struct adapter *, struct sge_wrq *, struct wrqe *);
void t4_update_fl_bufsize(struct ifnet *);
+struct mbuf *alloc_wr_mbuf(int, int);
int parse_pkt(struct adapter *, struct mbuf **);
void *start_wrq_wr(struct sge_wrq *, int, struct wrq_cookie *);
void commit_wrq_wr(struct sge_wrq *, void *, struct wrq_cookie *);
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 7593f9366f8f..3090bca5565a 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -529,9 +529,9 @@ struct intrs_and_queues {
static void setup_memwin(struct adapter *);
static void position_memwin(struct adapter *, int, uint32_t);
-static int validate_mem_range(struct adapter *, uint32_t, int);
+static int validate_mem_range(struct adapter *, uint32_t, uint32_t);
static int fwmtype_to_hwmtype(int);
-static int validate_mt_off_len(struct adapter *, int, uint32_t, int,
+static int validate_mt_off_len(struct adapter *, int, uint32_t, uint32_t,
uint32_t *);
static int fixup_devlog_params(struct adapter *);
static int cfg_itype_and_nqueues(struct adapter *, struct intrs_and_queues *);
@@ -2826,14 +2826,14 @@ t4_range_cmp(const void *a, const void *b)
* the card's address space.
*/
static int
-validate_mem_range(struct adapter *sc, uint32_t addr, int len)
+validate_mem_range(struct adapter *sc, uint32_t addr, uint32_t len)
{
struct t4_range mem_ranges[4], *r, *next;
uint32_t em, addr_len;
int i, n, remaining;
/* Memory can only be accessed in naturally aligned 4 byte units */
- if (addr & 3 || len & 3 || len <= 0)
+ if (addr & 3 || len & 3 || len == 0)
return (EINVAL);
/* Enabled memories */
@@ -2972,7 +2972,7 @@ fwmtype_to_hwmtype(int mtype)
* the start of the range is returned in addr.
*/
static int
-validate_mt_off_len(struct adapter *sc, int mtype, uint32_t off, int len,
+validate_mt_off_len(struct adapter *sc, int mtype, uint32_t off, uint32_t len,
uint32_t *addr)
{
uint32_t em, addr_len, maddr;
@@ -9804,6 +9804,7 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag,
txq->txpkts1_wrs = 0;
txq->txpkts0_pkts = 0;
txq->txpkts1_pkts = 0;
+ txq->raw_wrs = 0;
mp_ring_reset_stats(txq->r);
}
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 643eb29ffb9a..3660e333654e 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -82,6 +82,9 @@ __FBSDID("$FreeBSD$");
#define RX_COPY_THRESHOLD MINCLSIZE
#endif
+/* Internal mbuf flags stored in PH_loc.eight[1]. */
+#define MC_RAW_WR 0x02
+
/*
* Ethernet frames are DMA'd at this byte offset into the freelist buffer.
* 0-7 are valid values.
@@ -270,6 +273,7 @@ static inline u_int txpkt_len16(u_int, u_int);
static inline u_int txpkt_vm_len16(u_int, u_int);
static inline u_int txpkts0_len16(u_int);
static inline u_int txpkts1_len16(void);
+static u_int write_raw_wr(struct sge_txq *, void *, struct mbuf *, u_int);
static u_int write_txpkt_wr(struct sge_txq *, struct fw_eth_tx_pkt_wr *,
struct mbuf *, u_int);
static u_int write_txpkt_vm_wr(struct adapter *, struct sge_txq *,
@@ -2196,6 +2200,22 @@ set_mbuf_nsegs(struct mbuf *m, uint8_t nsegs)
}
static inline int
+mbuf_cflags(struct mbuf *m)
+{
+
+ M_ASSERTPKTHDR(m);
+ return (m->m_pkthdr.PH_loc.eight[4]);
+}
+
+static inline void
+set_mbuf_cflags(struct mbuf *m, uint8_t flags)
+{
+
+ M_ASSERTPKTHDR(m);
+ m->m_pkthdr.PH_loc.eight[4] = flags;
+}
+
+static inline int
mbuf_len16(struct mbuf *m)
{
int n;
@@ -2276,6 +2296,31 @@ needs_eo(struct mbuf *m)
}
#endif
+/*
+ * Try to allocate an mbuf to contain a raw work request. To make it
+ * easy to construct the work request, don't allocate a chain but a
+ * single mbuf.
+ */
+struct mbuf *
+alloc_wr_mbuf(int len, int how)
+{
+ struct mbuf *m;
+
+ if (len <= MHLEN)
+ m = m_gethdr(how, MT_DATA);
+ else if (len <= MCLBYTES)
+ m = m_getcl(how, MT_DATA, M_PKTHDR);
+ else
+ m = NULL;
+ if (m == NULL)
+ return (NULL);
+ m->m_pkthdr.len = len;
+ m->m_len = len;
+ set_mbuf_cflags(m, MC_RAW_WR);
+ set_mbuf_len16(m, howmany(len, 16));
+ return (m);
+}
+
static inline int
needs_tso(struct mbuf *m)
{
@@ -2449,6 +2494,7 @@ restart:
goto restart;
}
set_mbuf_nsegs(m0, nsegs);
+ set_mbuf_cflags(m0, 0);
if (sc->flags & IS_VF)
set_mbuf_len16(m0, txpkt_vm_len16(nsegs, needs_tso(m0)));
else
@@ -2691,7 +2737,7 @@ cannot_use_txpkts(struct mbuf *m)
{
/* maybe put a GL limit too, to avoid silliness? */
- return (needs_tso(m));
+ return (needs_tso(m) || (mbuf_cflags(m) & MC_RAW_WR) != 0);
}
static inline int
@@ -2701,6 +2747,21 @@ discard_tx(struct sge_eq *eq)
return ((eq->flags & (EQ_ENABLED | EQ_QFLUSH)) != EQ_ENABLED);
}
+static inline int
+wr_can_update_eq(struct fw_eth_tx_pkts_wr *wr)
+{
+
+ switch (G_FW_WR_OP(be32toh(wr->op_pkd))) {
+ case FW_ULPTX_WR:
+ case FW_ETH_TX_PKT_WR:
+ case FW_ETH_TX_PKTS_WR:
+ case FW_ETH_TX_PKT_VM_WR:
+ return (1);
+ default:
+ return (0);
+ }
+}
+
/*
* r->items[cidx] to r->items[pidx], with a wraparound at r->size, are ready to
* be consumed. Return the actual number consumed. 0 indicates a stall.
@@ -2796,6 +2857,10 @@ eth_tx(struct mp_ring *r, u_int cidx, u_int pidx)
n = write_txpkts_wr(txq, wr, m0, &txp, available);
total += txp.npkt;
remaining -= txp.npkt;
+ } else if (mbuf_cflags(m0) & MC_RAW_WR) {
+ total++;
+ remaining--;
+ n = write_raw_wr(txq, (void *)wr, m0, available);
} else {
total++;
remaining--;
@@ -2808,14 +2873,17 @@ eth_tx(struct mp_ring *r, u_int cidx, u_int pidx)
dbdiff += n;
IDXINCR(eq->pidx, n, eq->sidx);
- if (total_available_tx_desc(eq) < eq->sidx / 4 &&
- atomic_cmpset_int(&eq->equiq, 0, 1)) {
- wr->equiq_to_len16 |= htobe32(F_FW_WR_EQUIQ |
- F_FW_WR_EQUEQ);
- eq->equeqidx = eq->pidx;
- } else if (IDXDIFF(eq->pidx, eq->equeqidx, eq->sidx) >= 32) {
- wr->equiq_to_len16 |= htobe32(F_FW_WR_EQUEQ);
- eq->equeqidx = eq->pidx;
+ if (wr_can_update_eq(wr)) {
+ if (total_available_tx_desc(eq) < eq->sidx / 4 &&
+ atomic_cmpset_int(&eq->equiq, 0, 1)) {
+ wr->equiq_to_len16 |= htobe32(F_FW_WR_EQUIQ |
+ F_FW_WR_EQUEQ);
+ eq->equeqidx = eq->pidx;
+ } else if (IDXDIFF(eq->pidx, eq->equeqidx, eq->sidx) >=
+ 32) {
+ wr->equiq_to_len16 |= htobe32(F_FW_WR_EQUEQ);
+ eq->equeqidx = eq->pidx;
+ }
}
if (dbdiff >= 16 && remaining >= 4) {
@@ -4010,6 +4078,8 @@ alloc_txq(struct vi_info *vi, struct sge_txq *txq, int idx,
SYSCTL_ADD_UQUAD(&vi->ctx, children, OID_AUTO, "txpkts1_pkts",
CTLFLAG_RD, &txq->txpkts1_pkts,
"# of frames tx'd using type1 txpkts work requests");
+ SYSCTL_ADD_UQUAD(&vi->ctx, children, OID_AUTO, "raw_wrs", CTLFLAG_RD,
+ &txq->raw_wrs, "# of raw work requests (non-packets)");
SYSCTL_ADD_COUNTER_U64(&vi->ctx, children, OID_AUTO, "r_enqueues",
CTLFLAG_RD, &txq->r->enqueues,
@@ -4557,6 +4627,39 @@ write_txpkt_vm_wr(struct adapter *sc, struct sge_txq *txq,
}
/*
+ * Write a raw WR to the hardware descriptors, update the software
+ * descriptor, and advance the pidx. It is guaranteed that enough
+ * descriptors are available.
+ *
+ * The return value is the # of hardware descriptors used.
+ */
+static u_int
+write_raw_wr(struct sge_txq *txq, void *wr, struct mbuf *m0, u_int available)
+{
+ struct sge_eq *eq = &txq->eq;
+ struct tx_sdesc *txsd;
+ struct mbuf *m;
+ caddr_t dst;
+ int len16, ndesc;
+
+ len16 = mbuf_len16(m0);
+ ndesc = howmany(len16, EQ_ESIZE / 16);
+ MPASS(ndesc <= available);
+
+ dst = wr;
+ for (m = m0; m != NULL; m = m->m_next)
+ copy_to_txd(eq, mtod(m, caddr_t), &dst, m->m_len);
+
+ txq->raw_wrs++;
+
+ txsd = &txq->sdesc[eq->pidx];
+ txsd->m = m0;
+ txsd->desc_used = ndesc;
+
+ return (ndesc);
+}
+
+/*
* Write a txpkt WR for this packet to the hardware descriptors, update the
* software descriptor, and advance the pidx. It is guaranteed that enough
* descriptors are available.
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index f94f645b2e39..f0c0d41fa2b1 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -4949,8 +4949,11 @@ pmc_process_samples(int cpu, ring_type_t ring)
/* If there is a pending AST wait for completion */
if (ps->ps_nsamples == PMC_USER_CALLCHAIN_PENDING) {
- /* if sample is more than 65 ms old, drop it */
- if (ticks - ps->ps_ticks > (hz >> 4)) {
+ /* if we've been waiting more than 1 tick to
+ * collect a callchain for this record then
+ * drop it and move on.
+ */
+ if (ticks - ps->ps_ticks > 1) {
/*
* track how often we hit this as it will
* preferentially lose user samples
diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h
index 672b177ba908..280e1ed2f27b 100644
--- a/sys/dev/mrsas/mrsas.h
+++ b/sys/dev/mrsas/mrsas.h
@@ -612,8 +612,8 @@ typedef union {
#define mrsas_atomic_read(v) atomic_load_acq_int(&(v)->val)
#define mrsas_atomic_set(v,i) atomic_store_rel_int(&(v)->val, i)
-#define mrsas_atomic_dec(v) atomic_fetchadd_int(&(v)->val, -1)
-#define mrsas_atomic_inc(v) atomic_fetchadd_int(&(v)->val, 1)
+#define mrsas_atomic_dec(v) atomic_subtract_int(&(v)->val, 1)
+#define mrsas_atomic_inc(v) atomic_add_int(&(v)->val, 1)
/* IOCInit Request message */
typedef struct _MPI2_IOC_INIT_REQUEST {
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index 6c7b52fe76a6..35ce4eee52df 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -1432,6 +1432,19 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
goto receive_pkt;
}
} else if (td->ep_type == UE_ISOCHRONOUS) {
+ if (td->hcsplt != 0) {
+ /*
+ * Sometimes the complete
+ * split packet may be queued
+ * too early and the
+ * transaction translator will
+ * return a NAK. Ignore
+ * this message and retry the
+ * complete split instead.
+ */
+ DPRINTF("Retrying complete split\n");
+ goto receive_pkt;
+ }
goto complete;
}
td->did_nak = 1;
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index 96f93c060aba..d3587e89c552 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -1238,8 +1238,7 @@ nfs_mount(struct mount *mp)
bzero(&hst[hstlen], MNAMELEN - hstlen);
args.hostname = hst;
/* getsockaddr() call must be after above copyin() calls */
- error = getsockaddr(&nam, (caddr_t)args.addr,
- args.addrlen);
+ error = getsockaddr(&nam, args.addr, args.addrlen);
if (error != 0)
goto out;
} else if (nfs_mount_parse_from(mp->mnt_optnew,
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 47fd735d3b9e..7f9eb26e6ad3 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -3030,16 +3030,16 @@ nfs_advlock(struct vop_advlock_args *ap)
struct proc *p = (struct proc *)ap->a_id;
struct thread *td = curthread; /* XXX */
struct vattr va;
- int ret, error = EOPNOTSUPP;
+ int ret, error;
u_quad_t size;
- ret = NFSVOPLOCK(vp, LK_SHARED);
- if (ret != 0)
+ error = NFSVOPLOCK(vp, LK_SHARED);
+ if (error != 0)
return (EBADF);
if (NFS_ISV4(vp) && (ap->a_flags & (F_POSIX | F_FLOCK)) != 0) {
if (vp->v_type != VREG) {
- NFSVOPUNLOCK(vp, 0);
- return (EINVAL);
+ error = EINVAL;
+ goto out;
}
if ((ap->a_flags & F_POSIX) != 0)
cred = p->p_ucred;
@@ -3047,8 +3047,8 @@ nfs_advlock(struct vop_advlock_args *ap)
cred = td->td_ucred;
NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) {
- NFSVOPUNLOCK(vp, 0);
- return (EBADF);
+ error = EBADF;
+ goto out;
}
/*
@@ -3077,21 +3077,21 @@ nfs_advlock(struct vop_advlock_args *ap)
return (EINTR);
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) {
- NFSVOPUNLOCK(vp, 0);
- return (EBADF);
+ error = EBADF;
+ goto out;
}
}
} while (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) &&
ap->a_op == F_SETLK);
if (ret == NFSERR_DENIED) {
- NFSVOPUNLOCK(vp, 0);
- return (EAGAIN);
+ error = EAGAIN;
+ goto out;
} else if (ret == EINVAL || ret == EBADF || ret == EINTR) {
- NFSVOPUNLOCK(vp, 0);
- return (ret);
+ error = ret;
+ goto out;
} else if (ret != 0) {
- NFSVOPUNLOCK(vp, 0);
- return (EACCES);
+ error = EACCES;
+ goto out;
}
/*
@@ -3121,8 +3121,6 @@ nfs_advlock(struct vop_advlock_args *ap)
np->n_flag |= NHASBEENLOCKED;
mtx_unlock(&np->n_mtx);
}
- NFSVOPUNLOCK(vp, 0);
- return (0);
} else if (!NFS_ISV4(vp)) {
if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
size = VTONFS(vp)->n_size;
@@ -3146,8 +3144,11 @@ nfs_advlock(struct vop_advlock_args *ap)
NFSVOPUNLOCK(vp, 0);
}
}
+ return (error);
} else
- NFSVOPUNLOCK(vp, 0);
+ error = EOPNOTSUPP;
+out:
+ NFSVOPUNLOCK(vp, 0);
return (error);
}
diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c
index 9797884252ef..8a35b1e57d00 100644
--- a/sys/geom/geom_io.c
+++ b/sys/geom/geom_io.c
@@ -420,6 +420,8 @@ g_io_check(struct bio *bp)
return (EIO);
if (bp->bio_offset > pp->mediasize)
return (EIO);
+ if (bp->bio_offset == pp->mediasize && bp->bio_length > 0)
+ return (EIO);
/* Truncate requests to the end of providers media. */
excess = bp->bio_offset + bp->bio_length;
diff --git a/sys/i386/include/cpu.h b/sys/i386/include/cpu.h
index 8cd94fa7e1ff..8ba5e455f714 100644
--- a/sys/i386/include/cpu.h
+++ b/sys/i386/include/cpu.h
@@ -72,6 +72,7 @@ extern char btext[];
extern char etext[];
void cpu_halt(void);
+void cpu_lock_delay(void);
void cpu_reset(void);
void fork_trampoline(void);
void swi_vm(void *);
diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
index 7857d0862295..b5198b7a341c 100644
--- a/sys/kern/capabilities.conf
+++ b/sys/kern/capabilities.conf
@@ -486,9 +486,9 @@ pipe2
##
## Allow poll(2), which will be scoped by capability rights.
-## XXXRW: We don't yet do that scoping.
##
poll
+ppoll
##
## Allow I/O-related file descriptors, subject to capability rights.
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 885b5dc6f030..a567d0d83d95 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -594,7 +594,7 @@ struct sysent sysent[] = {
{ AS(pipe2_args), (sy_call_t *)sys_pipe2, AUE_PIPE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 542 = pipe2 */
{ AS(aio_mlock_args), (sy_call_t *)sys_aio_mlock, AUE_AIO_MLOCK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 543 = aio_mlock */
{ AS(procctl_args), (sy_call_t *)sys_procctl, AUE_PROCCTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 544 = procctl */
- { AS(ppoll_args), (sy_call_t *)sys_ppoll, AUE_POLL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 545 = ppoll */
+ { AS(ppoll_args), (sy_call_t *)sys_ppoll, AUE_POLL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 545 = ppoll */
{ AS(futimens_args), (sy_call_t *)sys_futimens, AUE_FUTIMES, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 546 = futimens */
{ AS(utimensat_args), (sy_call_t *)sys_utimensat, AUE_FUTIMESAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 547 = utimensat */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 548 = obsolete numa_getaffinity */
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
index c3f566dd0279..65c2e299bbc7 100644
--- a/sys/kern/kern_mutex.c
+++ b/sys/kern/kern_mutex.c
@@ -1206,7 +1206,7 @@ _mtx_lock_indefinite_check(struct mtx *m, struct lock_delay_arg *ldap)
ldap->spin_cnt++;
if (ldap->spin_cnt < 60000000 || kdb_active || panicstr != NULL)
- DELAY(1);
+ cpu_lock_delay();
else {
td = mtx_owner(m);
diff --git a/sys/kern/kern_ubsan.c b/sys/kern/kern_ubsan.c
new file mode 100644
index 000000000000..d6d60c5fa89e
--- /dev/null
+++ b/sys/kern/kern_ubsan.c
@@ -0,0 +1,1650 @@
+/* $NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+
+/*
+ * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
+ * The uBSSan versions is suitable for inclusion into libc or used standalone
+ * with ATF tests.
+ *
+ * This file due to long symbol names generated by a compiler during the
+ * instrumentation process does not follow the KNF style with 80-column limit.
+ */
+
+#include <sys/cdefs.h>
+#ifdef __FreeBSD__
+__FBSDID("$FreeBSD$");
+#else
+#if defined(_KERNEL)
+__KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
+#else
+__RCSID("$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
+#endif
+#endif
+
+#if defined(_KERNEL)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/limits.h>
+#include <sys/systm.h>
+#include <machine/_inttypes.h>
+#include <machine/stdarg.h>
+#define ASSERT(x) KASSERT(x, ("%s: " __STRING(x) " failed", __func__))
+#define __arraycount(x) nitems(x)
+#define ISSET(x, y) ((x) & (y))
+#define __BIT(x) ((uintmax_t)1 << (uintmax_t)(x))
+#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
+#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
+#else
+#if defined(_LIBC)
+#include "namespace.h"
+#endif
+#include <sys/param.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#if defined(_LIBC)
+#include "extern.h"
+#define ubsan_vsyslog vsyslog_ss
+#define ASSERT(x) _DIAGASSERT(x)
+#else
+#define ubsan_vsyslog vsyslog_r
+#define ASSERT(x) assert(x)
+#endif
+/* These macros are available in _KERNEL only */
+#define SET(t, f) ((t) |= (f))
+#define ISSET(t, f) ((t) & (f))
+#define CLR(t, f) ((t) &= ~(f))
+#endif
+
+#define REINTERPRET_CAST(__dt, __st) ((__dt)(__st))
+#define STATIC_CAST(__dt, __st) ((__dt)(__st))
+
+#define ACK_REPORTED __BIT(31)
+
+#define MUL_STRING "*"
+#define PLUS_STRING "+"
+#define MINUS_STRING "-"
+#define DIVREM_STRING "divrem"
+
+#define CFI_VCALL 0
+#define CFI_NVCALL 1
+#define CFI_DERIVEDCAST 2
+#define CFI_UNRELATEDCAST 3
+#define CFI_ICALL 4
+#define CFI_NVMFCALL 5
+#define CFI_VMFCALL 6
+
+#define NUMBER_MAXLEN 128
+#define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
+
+#define WIDTH_8 8
+#define WIDTH_16 16
+#define WIDTH_32 32
+#define WIDTH_64 64
+#define WIDTH_80 80
+#define WIDTH_96 96
+#define WIDTH_128 128
+
+#define NUMBER_SIGNED_BIT 1U
+
+#if __SIZEOF_INT128__
+typedef __int128 longest;
+typedef unsigned __int128 ulongest;
+#else
+typedef int64_t longest;
+typedef uint64_t ulongest;
+#endif
+
+#ifndef _KERNEL
+static int ubsan_flags = -1;
+#define UBSAN_ABORT __BIT(0)
+#define UBSAN_STDOUT __BIT(1)
+#define UBSAN_STDERR __BIT(2)
+#define UBSAN_SYSLOG __BIT(3)
+#endif
+
+/* Undefined Behavior specific defines and structures */
+
+#define KIND_INTEGER 0
+#define KIND_FLOAT 1
+#define KIND_UNKNOWN UINT16_MAX
+
+struct CSourceLocation {
+ char *mFilename;
+ uint32_t mLine;
+ uint32_t mColumn;
+};
+
+struct CTypeDescriptor {
+ uint16_t mTypeKind;
+ uint16_t mTypeInfo;
+ uint8_t mTypeName[1];
+};
+
+struct COverflowData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CUnreachableData {
+ struct CSourceLocation mLocation;
+};
+
+struct CCFICheckFailData {
+ uint8_t mCheckKind;
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CDynamicTypeCacheMissData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+ void *mTypeInfo;
+ uint8_t mTypeCheckKind;
+};
+
+struct CFunctionTypeMismatchData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CInvalidBuiltinData {
+ struct CSourceLocation mLocation;
+ uint8_t mKind;
+};
+
+struct CInvalidValueData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CNonNullArgData {
+ struct CSourceLocation mLocation;
+ struct CSourceLocation mAttributeLocation;
+ int mArgIndex;
+};
+
+struct CNonNullReturnData {
+ struct CSourceLocation mAttributeLocation;
+};
+
+struct COutOfBoundsData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mArrayType;
+ struct CTypeDescriptor *mIndexType;
+};
+
+struct CPointerOverflowData {
+ struct CSourceLocation mLocation;
+};
+
+struct CShiftOutOfBoundsData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mLHSType;
+ struct CTypeDescriptor *mRHSType;
+};
+
+struct CTypeMismatchData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+ unsigned long mLogAlignment;
+ uint8_t mTypeCheckKind;
+};
+
+struct CTypeMismatchData_v1 {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+ uint8_t mLogAlignment;
+ uint8_t mTypeCheckKind;
+};
+
+struct CVLABoundData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CFloatCastOverflowData {
+ struct CSourceLocation mLocation; /* This field exists in this struct since 2015 August 11th */
+ struct CTypeDescriptor *mFromType;
+ struct CTypeDescriptor *mToType;
+};
+
+/* Local utility functions */
+static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
+static bool isAlreadyReported(struct CSourceLocation *pLocation);
+static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
+static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
+#ifdef __SIZEOF_INT128__
+static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
+#endif
+static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
+static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
+#ifndef _KERNEL
+static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
+static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#endif
+static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#ifndef _KERNEL
+static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#endif
+static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
+static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
+static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
+static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
+
+/* Unused in this implementation, emitted by the C++ check dynamic type cast. */
+intptr_t __ubsan_vptr_type_cache[128];
+
+/* Public symbols used in the instrumentation of the code generation part */
+void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
+void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
+void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
+void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
+void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
+void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
+void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
+void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
+void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
+void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
+void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
+void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
+void __ubsan_handle_missing_return(struct CUnreachableData *pData);
+void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
+void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
+void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
+void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
+void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
+void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
+void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex);
+void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex);
+void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
+void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
+void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer);
+void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer);
+void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
+void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
+void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound);
+void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound);
+void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr);
+
+static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation);
+static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue);
+static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData);
+static void HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer);
+static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound);
+static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex);
+static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
+static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue);
+static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData);
+static void HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer);
+static void HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
+static void HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom);
+static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
+static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
+static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
+
+static void
+HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szLHS[NUMBER_MAXLEN];
+ char szRHS[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, ulLHS);
+ DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, ulRHS);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: %s %s %s cannot be represented in type %s\n",
+ szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
+}
+
+static void
+HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szOldValue[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
+ szLocation, szOldValue, pData->mType->mTypeName);
+}
+
+static void
+HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
+ szLocation);
+}
+
+static void
+HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ ASSERT(mLocation);
+ ASSERT(mType);
+
+ if (isAlreadyReported(mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
+
+ if (ulPointer == 0) {
+ Report(isFatal, "UBSan: Undefined Behavior in %s, %s null pointer of type %s\n",
+ szLocation, DeserializeTypeCheckKind(mTypeCheckKind), mType->mTypeName);
+ } else if ((mLogAlignment - 1) & ulPointer) {
+ Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned address %p for type %s which requires %ld byte alignment\n",
+ szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
+ } else {
+ Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p with insufficient space for an object of type %s\n",
+ szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
+ }
+}
+
+static void
+HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szBound[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
+ szLocation, szBound);
+}
+
+static void
+HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szIndex[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
+ szLocation, szIndex, pData->mArrayType->mTypeName);
+}
+
+static void
+HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szLHS[NUMBER_MAXLEN];
+ char szRHS[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, ulLHS);
+ DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, ulRHS);
+
+ if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
+ Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
+ szLocation, szRHS);
+ else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, zDeserializeTypeWidth(pData->mLHSType)))
+ Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is too large for %zu-bit type %s\n",
+ szLocation, szRHS, zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
+ else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
+ Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of negative value %s\n",
+ szLocation, szLHS);
+ else
+ Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of %s by %s places cannot be represented in type %s\n",
+ szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
+}
+
+static void
+HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szValue[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is not a valid value for type %s\n",
+ szLocation, szValue, pData->mType->mTypeName);
+}
+
+static void
+HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
+ szLocation, DeserializeBuiltinCheckKind(pData->mKind));
+}
+
+static void
+HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ /*
+ * There is no a portable C solution to translate an address of a
+ * function to its name. On the cost of getting this routine simple
+ * and portable without ifdefs between the userland and the kernel
+ * just print the address of the function as-is.
+ *
+ * For better diagnostic messages in the userland, users shall use
+ * the full upstream version shipped along with the compiler toolchain.
+ */
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx through pointer to incorrect function type %s\n",
+ szLocation, ulFunction, pData->mType->mTypeName);
+}
+
+static void
+HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ /*
+ * This is a minimal implementation without diving into C++
+ * specifics and (Itanium) ABI deserialization.
+ */
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) {
+ Report(isFatal, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx)\n",
+ szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
+ } else {
+ Report(isFatal || FromUnrecoverableHandler, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx; %s vtable; from %s handler; Program Counter %#lx; Frame Pointer %#lx)\n",
+ szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : "invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", *ProgramCounter, *FramePointer);
+ }
+}
+
+static void
+HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
+{
+#if 0
+ char szLocation[LOCATION_MAXLEN];
+
+ /*
+ * Unimplemented.
+ *
+ * This UBSan handler is special as the check has to be impelemented
+ * in an implementation. In order to handle it there is need to
+ * introspect into C++ ABI internals (RTTI) and use low-level
+ * C++ runtime interfaces.
+ */
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which might not point to an object of type %s\n"
+ szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), ulPointer, pData->mType);
+#endif
+}
+
+static void
+HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szFrom[NUMBER_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is outside the range of representable values of type %s\n",
+ szLocation, szFrom, pData->mFromType->mTypeName, pData->mToType->mTypeName);
+}
+
+static void
+HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
+ szLocation);
+}
+
+static void
+HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szAttributeLocation[LOCATION_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+ if (pData->mAttributeLocation.mFilename)
+ DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
+ else
+ szAttributeLocation[0] = '\0';
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed as argument %d, which is declared to never be null%s%s\n",
+ szLocation, pData->mArgIndex, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
+}
+
+static void
+HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
+{
+ char szLocation[LOCATION_MAXLEN];
+ char szAttributeLocation[LOCATION_MAXLEN];
+
+ ASSERT(pData);
+ ASSERT(pLocationPointer);
+
+ if (isAlreadyReported(pLocationPointer))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
+ if (pData->mAttributeLocation.mFilename)
+ DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
+ else
+ szAttributeLocation[0] = '\0';
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned from function declared to never return null%s%s\n",
+ szLocation, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
+}
+
+static void
+HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
+{
+ char szLocation[LOCATION_MAXLEN];
+
+ ASSERT(pData);
+
+ if (isAlreadyReported(&pData->mLocation))
+ return;
+
+ DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+ Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
+ szLocation, ulBase, ulResult);
+}
+
+/* Definions of public symbols emitted by the instrumentation code */
+void
+__ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
+}
+
+void
+__ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
+}
+
+void
+__ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleBuiltinUnreachable(true, pData);
+}
+
+void
+__ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
+{
+
+ ASSERT(pData);
+
+ HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
+}
+
+void
+__ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
+{
+
+ ASSERT(pData);
+
+ HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
+}
+
+void
+__ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
+{
+
+ ASSERT(pData);
+
+ HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
+}
+
+void
+__ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
+}
+
+void
+__ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
+}
+
+void
+__ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
+{
+
+ ASSERT(pData);
+
+ HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
+}
+
+void
+__ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
+{
+
+ ASSERT(pData);
+
+ HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
+}
+
+void
+__ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
+{
+
+ ASSERT(pData);
+
+ HandleFloatCastOverflow(false, pData, ulFrom);
+}
+
+void
+__ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
+{
+
+ ASSERT(pData);
+
+ HandleFloatCastOverflow(true, pData, ulFrom);
+}
+
+void
+__ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
+{
+
+ ASSERT(pData);
+
+ HandleFunctionTypeMismatch(false, pData, ulFunction);
+}
+
+void
+__ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
+{
+
+ ASSERT(pData);
+
+ HandleFunctionTypeMismatch(false, pData, ulFunction);
+}
+
+void
+__ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleInvalidBuiltin(true, pData);
+}
+
+void
+__ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleInvalidBuiltin(true, pData);
+}
+
+void
+__ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
+{
+
+ ASSERT(pData);
+
+ HandleLoadInvalidValue(false, pData, ulValue);
+}
+
+void
+__ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
+{
+
+ ASSERT(pData);
+
+ HandleLoadInvalidValue(true, pData, ulValue);
+}
+
+void
+__ubsan_handle_missing_return(struct CUnreachableData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleMissingReturn(true, pData);
+}
+
+void
+__ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
+}
+
+void
+__ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
+}
+
+void
+__ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
+{
+
+ ASSERT(pData);
+
+ HandleNegateOverflow(false, pData, ulOldValue);
+}
+
+void
+__ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
+{
+
+ ASSERT(pData);
+
+ HandleNegateOverflow(true, pData, ulOldValue);
+}
+
+void
+__ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleNonnullArg(false, pData);
+}
+
+void
+__ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleNonnullArg(true, pData);
+}
+
+void
+__ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
+{
+
+ ASSERT(pData);
+ ASSERT(pLocationPointer);
+
+ HandleNonnullReturn(false, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
+{
+
+ ASSERT(pData);
+ ASSERT(pLocationPointer);
+
+ HandleNonnullReturn(true, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleNonnullArg(false, pData);
+}
+
+void
+__ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
+{
+
+ ASSERT(pData);
+
+ HandleNonnullArg(true, pData);
+}
+
+void
+__ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
+{
+
+ ASSERT(pData);
+ ASSERT(pLocationPointer);
+
+ HandleNonnullReturn(false, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
+{
+
+ ASSERT(pData);
+ ASSERT(pLocationPointer);
+
+ HandleNonnullReturn(true, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
+{
+
+ ASSERT(pData);
+
+ HandleOutOfBounds(false, pData, ulIndex);
+}
+
+void
+__ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
+{
+
+ ASSERT(pData);
+
+ HandleOutOfBounds(true, pData, ulIndex);
+}
+
+void
+__ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
+{
+
+ ASSERT(pData);
+
+ HandlePointerOverflow(false, pData, ulBase, ulResult);
+}
+
+void
+__ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
+{
+
+ ASSERT(pData);
+
+ HandlePointerOverflow(true, pData, ulBase, ulResult);
+}
+
+void
+__ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
+}
+
+void
+__ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
+}
+
+void
+__ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
+}
+
+void
+__ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
+{
+
+ ASSERT(pData);
+
+ HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
+}
+
+void
+__ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
+{
+
+ ASSERT(pData);
+
+ HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
+}
+
+void
+__ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
+{
+
+ ASSERT(pData);
+
+ HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
+}
+
+void
+__ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
+{
+
+ ASSERT(pData);
+
+ HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
+}
+
+void
+__ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
+{
+
+ ASSERT(pData);
+
+ HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
+}
+
+void
+__ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
+{
+
+ ASSERT(pData);
+
+ HandleVlaBoundNotPositive(false, pData, ulBound);
+}
+
+void
+__ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
+{
+
+ ASSERT(pData);
+
+ HandleVlaBoundNotPositive(true, pData, ulBound);
+}
+
+void
+__ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
+{
+ /*
+ * Unimplemented.
+ *
+ * The __ubsan_on_report() feature is non trivial to implement in a
+ * shared code between the kernel and userland. It's also opening
+ * new sets of potential problems as we are not expected to slow down
+ * execution of certain kernel subsystems (synchronization issues,
+ * interrupt handling etc).
+ *
+ * A proper solution would need probably a lock-free bounded queue built
+ * with atomic operations with the property of miltiple consumers and
+ * multiple producers. Maintaining and validating such code is not
+ * worth the effort.
+ *
+ * A legitimate user - besides testing framework - is a debugger plugin
+ * intercepting reports from the UBSan instrumentation. For such
+ * scenarios it is better to run the Clang/GCC version.
+ */
+}
+
+/* Local utility functions */
+
+static void
+Report(bool isFatal, const char *pFormat, ...)
+{
+ va_list ap;
+
+ ASSERT(pFormat);
+
+ va_start(ap, pFormat);
+#if defined(_KERNEL)
+ if (isFatal)
+ vpanic(pFormat, ap);
+ else
+ vprintf(pFormat, ap);
+#else
+ if (ubsan_flags == -1) {
+ char buf[1024];
+ char *p;
+
+ ubsan_flags = UBSAN_STDERR;
+
+ if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
+ for (p = buf; *p; p++) {
+ switch (*p) {
+ case 'a':
+ SET(ubsan_flags, UBSAN_ABORT);
+ break;
+ case 'A':
+ CLR(ubsan_flags, UBSAN_ABORT);
+ break;
+ case 'e':
+ SET(ubsan_flags, UBSAN_STDERR);
+ break;
+ case 'E':
+ CLR(ubsan_flags, UBSAN_STDERR);
+ break;
+ case 'l':
+ SET(ubsan_flags, UBSAN_SYSLOG);
+ break;
+ case 'L':
+ CLR(ubsan_flags, UBSAN_SYSLOG);
+ break;
+ case 'o':
+ SET(ubsan_flags, UBSAN_STDOUT);
+ break;
+ case 'O':
+ CLR(ubsan_flags, UBSAN_STDOUT);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // The *v*print* functions can flush the va_list argument.
+ // Create a local copy for each call to prevent invalid read.
+ if (ISSET(ubsan_flags, UBSAN_STDOUT)) {
+ va_list tmp;
+ va_copy(tmp, ap);
+ vprintf(pFormat, tmp);
+ va_end(tmp);
+ fflush(stdout);
+ }
+ if (ISSET(ubsan_flags, UBSAN_STDERR)) {
+ va_list tmp;
+ va_copy(tmp, ap);
+ vfprintf(stderr, pFormat, tmp);
+ va_end(tmp);
+ fflush(stderr);
+ }
+ if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
+ va_list tmp;
+ va_copy(tmp, ap);
+ struct syslog_data SyslogData = SYSLOG_DATA_INIT;
+ ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
+ va_end(tmp);
+ }
+ if (isFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
+ abort();
+ /* NOTREACHED */
+ }
+#endif
+ va_end(ap);
+}
+
+static bool
+isAlreadyReported(struct CSourceLocation *pLocation)
+{
+ /*
+ * This code is shared between libc, kernel and standalone usage.
+ * It shall work in early bootstrap phase of both of them.
+ */
+
+ uint32_t siOldValue;
+ volatile uint32_t *pLine;
+
+ ASSERT(pLocation);
+
+ pLine = &pLocation->mLine;
+
+ do {
+ siOldValue = *pLine;
+ } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
+
+ return ISSET(siOldValue, ACK_REPORTED);
+}
+
+static size_t
+zDeserializeTypeWidth(struct CTypeDescriptor *pType)
+{
+ size_t zWidth = 0;
+
+ ASSERT(pType);
+
+ switch (pType->mTypeKind) {
+ case KIND_INTEGER:
+ zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
+ break;
+ case KIND_FLOAT:
+ zWidth = pType->mTypeInfo;
+ break;
+ default:
+ Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
+ /* NOTREACHED */
+ }
+
+ /* Invalid width will be transformed to 0 */
+ ASSERT(zWidth > 0);
+
+ return zWidth;
+}
+
+static void
+DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
+{
+
+ ASSERT(pLocation);
+ ASSERT(pLocation->mFilename);
+
+ snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
+}
+
+#ifdef __SIZEOF_INT128__
+static void
+DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
+{
+ char szBuf[3]; /* 'XX\0' */
+ char rgNumber[sizeof(ulongest)];
+ ssize_t zI;
+
+ memcpy(rgNumber, &U128, sizeof(U128));
+
+ strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
+#else
+ for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
+#endif
+ snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
+ strlcat(pBuffer, szBuf, zBUfferLength);
+ }
+ strlcat(pBuffer, ")", zBUfferLength);
+}
+#endif
+
+static void
+DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
+{
+
+ ASSERT(pBuffer);
+ ASSERT(zBUfferLength > 0);
+ ASSERT(pType);
+ ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
+
+ switch (zDeserializeTypeWidth(pType)) {
+ default:
+ ASSERT(0 && "Invalid codepath");
+ /* NOTREACHED */
+#ifdef __SIZEOF_INT128__
+ case WIDTH_128:
+ DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
+ break;
+#endif
+ case WIDTH_64:
+ case WIDTH_32:
+ case WIDTH_16:
+ case WIDTH_8:
+ snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
+ break;
+ }
+}
+
+static void
+DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
+{
+
+ ASSERT(pBuffer);
+ ASSERT(zBUfferLength > 0);
+ ASSERT(pType);
+ ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
+
+ switch (zDeserializeTypeWidth(pType)) {
+ default:
+ ASSERT(0 && "Invalid codepath");
+ /* NOTREACHED */
+#ifdef __SIZEOF_INT128__
+ case WIDTH_128:
+ DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
+ break;
+#endif
+ case WIDTH_64:
+ case WIDTH_32:
+ case WIDTH_16:
+ case WIDTH_8:
+ snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
+ break;
+ }
+}
+
+#ifndef _KERNEL
+static void
+DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
+{
+ double D;
+#ifdef __HAVE_LONG_DOUBLE
+ long double LD;
+#endif
+
+ ASSERT(pBuffer);
+ ASSERT(zBUfferLength > 0);
+ ASSERT(pType);
+ ASSERT(pNumber);
+ /*
+ * This function handles 64-bit number over a pointer on 32-bit CPUs.
+ */
+ ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
+ ASSERT(sizeof(D) == sizeof(uint64_t));
+#ifdef __HAVE_LONG_DOUBLE
+ ASSERT(sizeof(LD) > sizeof(uint64_t));
+#endif
+
+ switch (zDeserializeTypeWidth(pType)) {
+#ifdef __HAVE_LONG_DOUBLE
+ case WIDTH_128:
+ case WIDTH_96:
+ case WIDTH_80:
+ memcpy(&LD, pNumber, sizeof(long double));
+ snprintf(pBuffer, zBUfferLength, "%Lg", LD);
+ break;
+#endif
+ case WIDTH_64:
+ memcpy(&D, pNumber, sizeof(double));
+ snprintf(pBuffer, zBUfferLength, "%g", D);
+ break;
+ }
+}
+
+static void
+DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
+{
+ float F;
+ double D;
+ uint32_t U32;
+
+ ASSERT(pBuffer);
+ ASSERT(zBUfferLength > 0);
+ ASSERT(pType);
+ ASSERT(sizeof(F) == sizeof(uint32_t));
+ ASSERT(sizeof(D) == sizeof(uint64_t));
+
+ switch (zDeserializeTypeWidth(pType)) {
+ case WIDTH_64:
+ memcpy(&D, &ulNumber, sizeof(double));
+ snprintf(pBuffer, zBUfferLength, "%g", D);
+ break;
+ case WIDTH_32:
+ /*
+ * On supported platforms sizeof(float)==sizeof(uint32_t)
+ * unsigned long is either 32 or 64-bit, cast it to 32-bit
+ * value in order to call memcpy(3) in an Endian-aware way.
+ */
+ U32 = STATIC_CAST(uint32_t, ulNumber);
+ memcpy(&F, &U32, sizeof(float));
+ snprintf(pBuffer, zBUfferLength, "%g", F);
+ break;
+ case WIDTH_16:
+ snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
+ break;
+ }
+}
+#endif
+
+static longest
+llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
+{
+ size_t zNumberWidth;
+ longest L = 0;
+
+ ASSERT(szLocation);
+ ASSERT(pType);
+
+ zNumberWidth = zDeserializeTypeWidth(pType);
+ switch (zNumberWidth) {
+ default:
+ Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
+ /* NOTREACHED */
+ case WIDTH_128:
+#ifdef __SIZEOF_INT128__
+ memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
+#else
+ Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
+ /* NOTREACHED */
+#endif
+ break;
+ case WIDTH_64:
+ if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
+ L = *REINTERPRET_CAST(int64_t *, ulNumber);
+ } else {
+ L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
+ }
+ break;
+ case WIDTH_32:
+ L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
+ break;
+ case WIDTH_16:
+ L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
+ break;
+ case WIDTH_8:
+ L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
+ break;
+ }
+
+ return L;
+}
+
+static ulongest
+llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
+{
+ size_t zNumberWidth;
+ ulongest UL = 0;
+
+ ASSERT(pType);
+
+ zNumberWidth = zDeserializeTypeWidth(pType);
+ switch (zNumberWidth) {
+ default:
+ Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
+ /* NOTREACHED */
+ case WIDTH_128:
+#ifdef __SIZEOF_INT128__
+ memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
+ break;
+#else
+ Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
+ /* NOTREACHED */
+#endif
+ case WIDTH_64:
+ if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
+ UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
+ break;
+ }
+ /* FALLTHROUGH */
+ case WIDTH_32:
+ /* FALLTHROUGH */
+ case WIDTH_16:
+ /* FALLTHROUGH */
+ case WIDTH_8:
+ UL = ulNumber;
+ break;
+ }
+
+ return UL;
+}
+
+#ifndef _KERNEL
+static void
+DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
+{
+ size_t zNumberWidth;
+
+ ASSERT(szLocation);
+ ASSERT(pBuffer);
+ ASSERT(zBUfferLength > 0);
+ ASSERT(pType);
+ ASSERT(pType->mTypeKind == KIND_FLOAT);
+
+ zNumberWidth = zDeserializeTypeWidth(pType);
+ switch (zNumberWidth) {
+ default:
+ Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
+ /* NOTREACHED */
+#ifdef __HAVE_LONG_DOUBLE
+ case WIDTH_128:
+ case WIDTH_96:
+ case WIDTH_80:
+ DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
+ break;
+#endif
+ case WIDTH_64:
+ if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
+ DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
+ break;
+ }
+ case WIDTH_32:
+ case WIDTH_16:
+ DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
+ break;
+ }
+}
+#endif
+
+static void
+DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
+{
+
+ ASSERT(szLocation);
+ ASSERT(pBuffer);
+ ASSERT(zBUfferLength > 0);
+ ASSERT(pType);
+
+ switch(pType->mTypeKind) {
+ case KIND_INTEGER:
+ if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
+ longest L = llliGetNumber(szLocation, pType, ulNumber);
+ DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
+ } else {
+ ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
+ DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
+ }
+ break;
+ case KIND_FLOAT:
+#ifdef _KERNEL
+ Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
+ /* NOTREACHED */
+#else
+ DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
+#endif
+ break;
+ case KIND_UNKNOWN:
+ Report(true, "UBSan: Unknown Type in %s\n", szLocation);
+ /* NOTREACHED */
+ break;
+ }
+}
+
+static const char *
+DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
+{
+ const char *rgczTypeCheckKinds[] = {
+ "load of",
+ "store to",
+ "reference binding to",
+ "member access within",
+ "member call on",
+ "constructor call on",
+ "downcast of",
+ "downcast of",
+ "upcast of",
+ "cast to virtual base of",
+ "_Nonnull binding to",
+ "dynamic operation on"
+ };
+
+ ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
+
+ return rgczTypeCheckKinds[hhuTypeCheckKind];
+}
+
+static const char *
+DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
+{
+ const char *rgczBuiltinCheckKinds[] = {
+ "ctz()",
+ "clz()"
+ };
+
+ ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
+
+ return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
+}
+
+static const char *
+DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
+{
+ const char *rgczCFICheckKinds[] = {
+ "virtual call", // CFI_VCALL
+ "non-virtual call", // CFI_NVCALL
+ "base-to-derived cast", // CFI_DERIVEDCAST
+ "cast to unrelated type", // CFI_UNRELATEDCAST
+ "indirect function call", // CFI_ICALL
+ "non-virtual pointer to member function call", // CFI_NVMFCALL
+ "virtual pointer to member function call", // CFI_VMFCALL
+ };
+
+ ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
+
+ return rgczCFICheckKinds[hhuCFICheckKind];
+}
+
+static bool
+isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
+{
+
+ ASSERT(szLocation);
+ ASSERT(pType);
+ ASSERT(pType->mTypeKind == KIND_INTEGER);
+
+ if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
+ return false;
+
+ return llliGetNumber(szLocation, pType, ulNumber) < 0;
+}
+
+static bool
+isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
+{
+
+ ASSERT(szLocation);
+ ASSERT(pType);
+ ASSERT(pType->mTypeKind == KIND_INTEGER);
+
+ return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
+}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 56eba3dd22db..8b0aaa9ab4cf 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -509,9 +509,8 @@ retry:
size = round_page(size);
buffer = (caddr_t) vm_map_min(pipe_map);
- error = vm_map_find(pipe_map, NULL, 0,
- (vm_offset_t *) &buffer, size, 0, VMFS_ANY_SPACE,
- VM_PROT_ALL, VM_PROT_ALL, 0);
+ error = vm_map_find(pipe_map, NULL, 0, (vm_offset_t *)&buffer, size, 0,
+ VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
if (error != KERN_SUCCESS) {
if ((cpipe->pipe_buffer.buffer == NULL) &&
(size > SMALL_PIPE_SIZE)) {
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index dfe6677de120..55d81c059d5e 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -117,8 +117,7 @@
);
}
; XXX should be { int open(const char *path, int flags, ...); }
-; but we're not ready for `const' or varargs.
-; XXX man page says `mode_t mode'.
+; but we're not ready for varargs.
6 AUE_CLOSE STD {
int close(
int fd
@@ -207,10 +206,9 @@
_In_z_ const char *type,
_In_z_ const char *path,
int flags,
- _In_opt_ caddr_t data
+ _In_opt_ void *data
);
}
-; XXX `path' should have type `const char *' but we're not ready for that.
22 AUE_UMOUNT STD {
int unmount(
_In_z_ const char *path,
@@ -253,7 +251,7 @@
29 AUE_RECVFROM STD {
int recvfrom(
int s,
- _Out_writes_bytes_(len) caddr_t buf,
+ _Out_writes_bytes_(len) void *buf,
size_t len,
int flags,
_Out_writes_bytes_opt_(*fromlenaddr) struct sockaddr *from,
@@ -336,7 +334,7 @@
}
44 AUE_PROFILE STD {
int profil(
- _Out_writes_bytes_(size) caddr_t samples,
+ _Out_writes_bytes_(size) char *samples,
size_t size,
size_t offset,
u_int scale
@@ -398,7 +396,7 @@
int ioctl(
int fd,
u_long com,
- _Inout_opt_ caddr_t data
+ _Inout_opt_ char *data
);
}
55 AUE_REBOOT STD {
@@ -630,14 +628,14 @@
98 AUE_CONNECT STD {
int connect(
int s,
- _In_reads_bytes_(namelen) caddr_t name,
+ _In_reads_bytes_(namelen) const struct sockaddr *name,
int namelen
);
}
99 AUE_ACCEPT COMPAT|NOARGS {
int accept(
int s,
- _Out_writes_bytes_opt_(*anamelen) caddr_t name,
+ _Out_writes_bytes_opt_(*anamelen) struct sockaddr *name,
int *anamelen
);
} accept accept_args int
@@ -650,7 +648,7 @@
101 AUE_SEND COMPAT {
int send(
int s,
- _In_reads_bytes_(len) caddr_t buf,
+ _In_reads_bytes_(len) const void *buf,
int len,
int flags
);
@@ -658,7 +656,7 @@
102 AUE_RECV COMPAT {
int recv(
int s,
- _Out_writes_bytes_(len) caddr_t buf,
+ _Out_writes_bytes_(len) void *buf,
int len,
int flags
);
@@ -671,7 +669,7 @@
104 AUE_BIND STD {
int bind(
int s,
- _In_reads_bytes_(namelen) caddr_t name,
+ _In_reads_bytes_(namelen) const struct sockaddr *name,
int namelen
);
}
@@ -680,7 +678,7 @@
int s,
int level,
int name,
- _In_reads_bytes_opt_(valsize) caddr_t val,
+ _In_reads_bytes_opt_(valsize) const void *val,
int valsize
);
}
@@ -731,7 +729,7 @@
114 AUE_SENDMSG COMPAT {
int sendmsg(
int s,
- _In_ caddr_t msg,
+ _In_ const void *msg,
int flags
);
}
@@ -753,7 +751,7 @@
int s,
int level,
int name,
- _Out_writes_bytes_opt_(*avalsize) caddr_t val,
+ _Out_writes_bytes_opt_(*avalsize) void *val,
_Inout_ int *avalsize
);
}
@@ -761,8 +759,8 @@
120 AUE_READV STD {
int readv(
int fd,
- _Inout_updates_(iovcnt) struct iovec *iovp,
- u_int iovcnt
+ _Inout_updates_(iovcnt) struct iovec *iovp,
+ u_int iovcnt
);
}
121 AUE_WRITEV STD {
@@ -794,10 +792,10 @@
125 AUE_RECVFROM COMPAT|NOARGS {
int recvfrom(
int s,
- _Out_writes_(len) caddr_t buf,
+ _Out_writes_(len) void *buf,
size_t len,
int flags,
- _Out_writes_bytes_(*fromlenaddr) caddr_t from,
+ _Out_writes_bytes_(*fromlenaddr) struct sockaddr *from,
_Inout_ int *fromlenaddr
);
} recvfrom recvfrom_args int
@@ -846,10 +844,10 @@
133 AUE_SENDTO STD {
int sendto(
int s,
- _In_reads_bytes_(len) caddr_t buf,
+ _In_reads_bytes_(len) const void *buf,
size_t len,
- int flags,
- _In_reads_bytes_opt_(tolen) caddr_t to,
+ int flags,
+ _In_reads_bytes_opt_(tolen) const struct sockaddr *to,
int tolen
);
}
@@ -894,7 +892,7 @@
141 AUE_GETPEERNAME COMPAT {
int getpeername(
int fdes,
- _Out_writes_bytes_(*alen) caddr_t asa,
+ _Out_writes_bytes_(*alen) struct sockaddr *asa,
_Inout_opt_ int *alen
);
}
@@ -932,7 +930,7 @@
_In_z_ const char *path,
int cmd,
int uid,
- _In_ caddr_t arg
+ _In_ void *arg
);
}
149 AUE_O_QUOTA COMPAT {
@@ -941,7 +939,7 @@
150 AUE_GETSOCKNAME COMPAT|NOARGS {
int getsockname(
int fdec,
- _Out_writes_bytes_(*alen) caddr_t asa,
+ _Out_writes_bytes_(*alen) struct sockaddr *asa,
_Inout_ int *alen
);
} getsockname getsockname_args int
@@ -966,7 +964,7 @@
155 AUE_NFS_SVC NOSTD {
int nfssvc(
int flag,
- _In_ caddr_t argp
+ _In_ void *argp
);
}
156 AUE_GETDIRENTRIES COMPAT {
@@ -1171,7 +1169,7 @@
}
197 AUE_MMAP COMPAT6 {
caddr_t mmap(
- _In_ caddr_t addr,
+ _In_ void *addr,
size_t len,
int prot,
int flags,
@@ -2498,9 +2496,9 @@
472 AUE_SCTP_GENERIC_SENDMSG NOSTD {
int sctp_generic_sendmsg(
int sd,
- _In_reads_bytes_(mlen) caddr_t msg,
+ _In_reads_bytes_(mlen) void *msg,
int mlen,
- _In_reads_bytes_(tolen) caddr_t to,
+ _In_reads_bytes_(tolen) struct sockaddr *to,
__socklen_t tolen,
_In_opt_ struct sctp_sndrcvinfo *sinfo,
int flags
@@ -2511,7 +2509,7 @@
int sd,
_In_reads_(iovlen) struct iovec *iov,
int iovlen,
- _In_reads_bytes_(tolen) caddr_t to,
+ _In_reads_bytes_(tolen) struct sockaddr *to,
__socklen_t tolen,
_In_opt_ struct sctp_sndrcvinfo *sinfo,
int flags
@@ -2546,7 +2544,7 @@
}
477 AUE_MMAP STD {
caddr_t mmap(
- _In_ caddr_t addr,
+ _In_ void *addr,
size_t len,
int prot,
int flags,
@@ -2967,7 +2965,7 @@
int bindat(
int fd,
int s,
- _In_reads_bytes_(namelen) caddr_t name,
+ _In_reads_bytes_(namelen) const struct sockaddr *name,
int namelen
);
}
@@ -2975,7 +2973,7 @@
int connectat(
int fd,
int s,
- _In_reads_bytes_(namelen) caddr_t name,
+ _In_reads_bytes_(namelen) const struct sockaddr *name,
int namelen
);
}
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
index 31283b9df1f0..9061b6eb6a89 100644
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -136,7 +136,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
uarg[0] = (intptr_t) p->type; /* const char * */
uarg[1] = (intptr_t) p->path; /* const char * */
iarg[2] = p->flags; /* int */
- uarg[3] = (intptr_t) p->data; /* caddr_t */
+ uarg[3] = (intptr_t) p->data; /* void * */
*n_args = 4;
break;
}
@@ -197,7 +197,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 29: {
struct recvfrom_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->buf; /* caddr_t */
+ uarg[1] = (intptr_t) p->buf; /* void * */
uarg[2] = p->len; /* size_t */
iarg[3] = p->flags; /* int */
uarg[4] = (intptr_t) p->from; /* struct sockaddr * */
@@ -289,7 +289,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* profil */
case 44: {
struct profil_args *p = params;
- uarg[0] = (intptr_t) p->samples; /* caddr_t */
+ uarg[0] = (intptr_t) p->samples; /* char * */
uarg[1] = p->size; /* size_t */
uarg[2] = p->offset; /* size_t */
uarg[3] = p->scale; /* u_int */
@@ -346,7 +346,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct ioctl_args *p = params;
iarg[0] = p->fd; /* int */
uarg[1] = p->com; /* u_long */
- uarg[2] = (intptr_t) p->data; /* caddr_t */
+ uarg[2] = (intptr_t) p->data; /* char * */
*n_args = 3;
break;
}
@@ -582,7 +582,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 98: {
struct connect_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->name; /* caddr_t */
+ uarg[1] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[2] = p->namelen; /* int */
*n_args = 3;
break;
@@ -599,7 +599,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 104: {
struct bind_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->name; /* caddr_t */
+ uarg[1] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[2] = p->namelen; /* int */
*n_args = 3;
break;
@@ -610,7 +610,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->s; /* int */
iarg[1] = p->level; /* int */
iarg[2] = p->name; /* int */
- uarg[3] = (intptr_t) p->val; /* caddr_t */
+ uarg[3] = (intptr_t) p->val; /* const void * */
iarg[4] = p->valsize; /* int */
*n_args = 5;
break;
@@ -645,7 +645,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->s; /* int */
iarg[1] = p->level; /* int */
iarg[2] = p->name; /* int */
- uarg[3] = (intptr_t) p->val; /* caddr_t */
+ uarg[3] = (intptr_t) p->val; /* void * */
uarg[4] = (intptr_t) p->avalsize; /* int * */
*n_args = 5;
break;
@@ -737,10 +737,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 133: {
struct sendto_args *p = params;
iarg[0] = p->s; /* int */
- uarg[1] = (intptr_t) p->buf; /* caddr_t */
+ uarg[1] = (intptr_t) p->buf; /* const void * */
uarg[2] = p->len; /* size_t */
iarg[3] = p->flags; /* int */
- uarg[4] = (intptr_t) p->to; /* caddr_t */
+ uarg[4] = (intptr_t) p->to; /* const struct sockaddr * */
iarg[5] = p->tolen; /* int */
*n_args = 6;
break;
@@ -805,7 +805,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
uarg[0] = (intptr_t) p->path; /* const char * */
iarg[1] = p->cmd; /* int */
iarg[2] = p->uid; /* int */
- uarg[3] = (intptr_t) p->arg; /* caddr_t */
+ uarg[3] = (intptr_t) p->arg; /* void * */
*n_args = 4;
break;
}
@@ -823,7 +823,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 155: {
struct nfssvc_args *p = params;
iarg[0] = p->flag; /* int */
- uarg[1] = (intptr_t) p->argp; /* caddr_t */
+ uarg[1] = (intptr_t) p->argp; /* void * */
*n_args = 2;
break;
}
@@ -2474,9 +2474,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 472: {
struct sctp_generic_sendmsg_args *p = params;
iarg[0] = p->sd; /* int */
- uarg[1] = (intptr_t) p->msg; /* caddr_t */
+ uarg[1] = (intptr_t) p->msg; /* void * */
iarg[2] = p->mlen; /* int */
- uarg[3] = (intptr_t) p->to; /* caddr_t */
+ uarg[3] = (intptr_t) p->to; /* struct sockaddr * */
iarg[4] = p->tolen; /* __socklen_t */
uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
iarg[6] = p->flags; /* int */
@@ -2489,7 +2489,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->sd; /* int */
uarg[1] = (intptr_t) p->iov; /* struct iovec * */
iarg[2] = p->iovlen; /* int */
- uarg[3] = (intptr_t) p->to; /* caddr_t */
+ uarg[3] = (intptr_t) p->to; /* struct sockaddr * */
iarg[4] = p->tolen; /* __socklen_t */
uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
iarg[6] = p->flags; /* int */
@@ -2532,7 +2532,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* mmap */
case 477: {
struct mmap_args *p = params;
- uarg[0] = (intptr_t) p->addr; /* caddr_t */
+ uarg[0] = (intptr_t) p->addr; /* void * */
uarg[1] = p->len; /* size_t */
iarg[2] = p->prot; /* int */
iarg[3] = p->flags; /* int */
@@ -3047,7 +3047,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct bindat_args *p = params;
iarg[0] = p->fd; /* int */
iarg[1] = p->s; /* int */
- uarg[2] = (intptr_t) p->name; /* caddr_t */
+ uarg[2] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[3] = p->namelen; /* int */
*n_args = 4;
break;
@@ -3057,7 +3057,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct connectat_args *p = params;
iarg[0] = p->fd; /* int */
iarg[1] = p->s; /* int */
- uarg[2] = (intptr_t) p->name; /* caddr_t */
+ uarg[2] = (intptr_t) p->name; /* const struct sockaddr * */
iarg[3] = p->namelen; /* int */
*n_args = 4;
break;
@@ -3467,7 +3467,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland void *";
break;
default:
break;
@@ -3560,7 +3560,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland void *";
break;
case 2:
p = "size_t";
@@ -3701,7 +3701,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 44:
switch(ndx) {
case 0:
- p = "caddr_t";
+ p = "userland char *";
break;
case 1:
p = "size_t";
@@ -3794,7 +3794,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "u_long";
break;
case 2:
- p = "caddr_t";
+ p = "userland char *";
break;
default:
break;
@@ -4169,7 +4169,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 2:
p = "int";
@@ -4198,7 +4198,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 2:
p = "int";
@@ -4220,7 +4220,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland const void *";
break;
case 4:
p = "int";
@@ -4281,7 +4281,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland void *";
break;
case 4:
p = "userland int *";
@@ -4436,7 +4436,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland const void *";
break;
case 2:
p = "size_t";
@@ -4445,7 +4445,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 4:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 5:
p = "int";
@@ -4551,7 +4551,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland void *";
break;
default:
break;
@@ -4583,7 +4583,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland void *";
break;
default:
break;
@@ -7276,13 +7276,13 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 1:
- p = "caddr_t";
+ p = "userland void *";
break;
case 2:
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 4:
p = "__socklen_t";
@@ -7310,7 +7310,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 3:
- p = "caddr_t";
+ p = "userland struct sockaddr *";
break;
case 4:
p = "__socklen_t";
@@ -7395,7 +7395,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 477:
switch(ndx) {
case 0:
- p = "caddr_t";
+ p = "userland void *";
break;
case 1:
p = "size_t";
@@ -8312,7 +8312,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 2:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 3:
p = "int";
@@ -8331,7 +8331,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "int";
break;
case 2:
- p = "caddr_t";
+ p = "userland const struct sockaddr *";
break;
case 3:
p = "int";
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 26ce6124bf86..022c392d5c17 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include "opt_capsicum.h"
+#include "opt_printf.h"
#include <sys/param.h>
#include <sys/capsicum.h>
@@ -106,6 +107,12 @@ SYSCTL_INT(_kern, OID_AUTO, tty_drainwait, CTLFLAG_RWTUN,
#define TTYBUF_MAX 65536
+#ifdef PRINTF_BUFR_SIZE
+#define TTY_PRBUF_SIZE PRINTF_BUFR_SIZE
+#else
+#define TTY_PRBUF_SIZE 256
+#endif
+
/*
* Allocate buffer space if necessary, and set low watermarks, based on speed.
* Note that the ttyxxxq_setsize() functions may drop and then reacquire the tty
@@ -1051,7 +1058,9 @@ tty_alloc_mutex(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
PATCH_FUNC(busy);
#undef PATCH_FUNC
- tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
+ tp = malloc(sizeof(struct tty) + TTY_PRBUF_SIZE, M_TTY,
+ M_WAITOK | M_ZERO);
+ tp->t_prbufsz = TTY_PRBUF_SIZE;
tp->t_devsw = tsw;
tp->t_devswsoftc = sc;
tp->t_flags = tsw->tsw_flags;
diff --git a/sys/kern/tty_info.c b/sys/kern/tty_info.c
index 378e1bc64284..47e65565848d 100644
--- a/sys/kern/tty_info.c
+++ b/sys/kern/tty_info.c
@@ -45,6 +45,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_stack.h"
+
#include <sys/param.h>
#include <sys/cons.h>
#include <sys/kdb.h>
@@ -269,7 +271,7 @@ tty_info(struct tty *tp)
if (tty_checkoutq(tp) == 0)
return;
- (void)sbuf_new(&sb, tp->t_prbuf, sizeof(tp->t_prbuf), SBUF_FIXEDLEN);
+ (void)sbuf_new(&sb, tp->t_prbuf, tp->t_prbufsz, SBUF_FIXEDLEN);
sbuf_set_drain(&sb, sbuf_tty_drain, tp);
/* Print load average. */
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 4751635e2aee..2f5cad6466d8 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -393,7 +393,7 @@ mqnode_free(struct mqfs_node *node)
static __inline void
mqnode_addref(struct mqfs_node *node)
{
- atomic_fetchadd_int(&node->mn_refcount, 1);
+ atomic_add_int(&node->mn_refcount, 1);
}
static __inline void
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 57cddd153972..202d5c868de4 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -825,7 +825,7 @@ sys_sendto(struct thread *td, struct sendto_args *uap)
struct msghdr msg;
struct iovec aiov;
- msg.msg_name = uap->to;
+ msg.msg_name = __DECONST(void *, uap->to);
msg.msg_namelen = uap->tolen;
msg.msg_iov = &aiov;
msg.msg_iovlen = 1;
@@ -833,7 +833,7 @@ sys_sendto(struct thread *td, struct sendto_args *uap)
#ifdef COMPAT_OLDSOCK
msg.msg_flags = 0;
#endif
- aiov.iov_base = uap->buf;
+ aiov.iov_base = __DECONST(void *, uap->buf);
aiov.iov_len = uap->len;
return (sendit(td, uap->s, &msg, uap->flags));
}
@@ -849,7 +849,7 @@ osend(struct thread *td, struct osend_args *uap)
msg.msg_namelen = 0;
msg.msg_iov = &aiov;
msg.msg_iovlen = 1;
- aiov.iov_base = uap->buf;
+ aiov.iov_base = __DECONST(void *, uap->buf);
aiov.iov_len = uap->len;
msg.msg_control = 0;
msg.msg_flags = 0;
@@ -1225,7 +1225,7 @@ sys_setsockopt(struct thread *td, struct setsockopt_args *uap)
}
int
-kern_setsockopt(struct thread *td, int s, int level, int name, void *val,
+kern_setsockopt(struct thread *td, int s, int level, int name, const void *val,
enum uio_seg valseg, socklen_t valsize)
{
struct socket *so;
@@ -1241,7 +1241,7 @@ kern_setsockopt(struct thread *td, int s, int level, int name, void *val,
sopt.sopt_dir = SOPT_SET;
sopt.sopt_level = level;
sopt.sopt_name = name;
- sopt.sopt_val = val;
+ sopt.sopt_val = __DECONST(void *, val);
sopt.sopt_valsize = valsize;
switch (valseg) {
case UIO_USERSPACE:
@@ -1546,7 +1546,7 @@ sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type)
}
int
-getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
+getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len)
{
struct sockaddr *sa;
int error;
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 83e67207dc9f..ea322343d89a 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1656,7 +1656,7 @@ buf_alloc(struct bufdomain *bd)
if (freebufs > 0)
bp = uma_zalloc(buf_zone, M_NOWAIT);
if (bp == NULL) {
- atomic_fetchadd_int(&bd->bd_freebuffers, 1);
+ atomic_add_int(&bd->bd_freebuffers, 1);
bufspace_daemon_wakeup(bd);
counter_u64_add(numbufallocfails, 1);
return (NULL);
diff --git a/sys/mips/include/cpu.h b/sys/mips/include/cpu.h
index a54ea2a2d6bf..b4f5c59f72f5 100644
--- a/sys/mips/include/cpu.h
+++ b/sys/mips/include/cpu.h
@@ -71,6 +71,7 @@
#define cpu_getstack(td) ((td)->td_frame->sp)
#define cpu_setstack(td, nsp) ((td)->td_frame->sp = (nsp))
#define cpu_spinwait() /* nothing */
+#define cpu_lock_delay() DELAY(1)
/*
* A machine-independent interface to the CPU's counter.
diff --git a/sys/netgraph/ng_pptpgre.c b/sys/netgraph/ng_pptpgre.c
index 0941d8eb7d18..6ad7516a5dbc 100644
--- a/sys/netgraph/ng_pptpgre.c
+++ b/sys/netgraph/ng_pptpgre.c
@@ -64,6 +64,7 @@
#include <sys/mutex.h>
#include <sys/endian.h>
#include <sys/errno.h>
+#include <sys/sysctl.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -124,6 +125,8 @@ typedef u_int64_t pptptime_t;
#define PPTP_MIN_TIMEOUT (PPTP_TIME_SCALE / 83) /* 12 milliseconds */
#define PPTP_MAX_TIMEOUT (3 * PPTP_TIME_SCALE) /* 3 seconds */
+#define PPTP_REORDER_TIMEOUT 1
+
/* When we receive a packet, we wait to see if there's an outgoing packet
we can piggy-back the ACK off of. These parameters determine the mimimum
and maxmimum length of time we're willing to wait in order to do that.
@@ -142,6 +145,34 @@ typedef u_int64_t pptptime_t;
#define SESSHASHSIZE 0x0020
#define SESSHASH(x) (((x) ^ ((x) >> 8)) & (SESSHASHSIZE - 1))
+SYSCTL_NODE(_net_graph, OID_AUTO, pptpgre, CTLFLAG_RW, 0, "PPTPGRE");
+
+/*
+ * Reorder queue maximum length. Zero disables reorder.
+ *
+ * The node may keep reorder_max queue entries per session
+ * if reorder is enabled, plus allocate one more for short time.
+ *
+ * Be conservative in memory consumption by default.
+ * Lots of sessions with large queues can overflow M_NETGRAPH zone.
+ */
+static int reorder_max = 1; /* reorder up to two swapped packets in a row */
+SYSCTL_UINT(_net_graph_pptpgre, OID_AUTO, reorder_max, CTLFLAG_RWTUN,
+ &reorder_max, 0, "Reorder queue maximum length");
+
+static int reorder_timeout = PPTP_REORDER_TIMEOUT;
+SYSCTL_UINT(_net_graph_pptpgre, OID_AUTO, reorder_timeout, CTLFLAG_RWTUN,
+ &reorder_timeout, 0, "Reorder timeout is milliseconds");
+
+/* Packet reorder FIFO queue */
+struct ng_pptpgre_roq {
+ SLIST_ENTRY(ng_pptpgre_roq) next; /* next entry of the queue */
+ item_p item; /* netgraph item */
+ u_int32_t seq; /* packet sequence number */
+};
+SLIST_HEAD(ng_pptpgre_roq_head, ng_pptpgre_roq);
+typedef struct ng_pptpgre_roq_head roqh;
+
/* We keep packet retransmit and acknowlegement state in this struct */
struct ng_pptpgre_sess {
node_p node; /* this node pointer */
@@ -161,6 +192,9 @@ struct ng_pptpgre_sess {
u_int32_t winAck; /* seq when xmitWin will grow */
pptptime_t timeSent[PPTP_XMIT_WIN];
LIST_ENTRY(ng_pptpgre_sess) sessions;
+ roqh roq; /* reorder queue head */
+ u_int8_t roq_len; /* reorder queue length */
+ struct callout reorderTimer; /* reorder timeout handler */
};
typedef struct ng_pptpgre_sess *hpriv_p;
@@ -187,13 +221,19 @@ static ng_disconnect_t ng_pptpgre_disconnect;
static int ng_pptpgre_xmit(hpriv_p hpriv, item_p item);
static void ng_pptpgre_start_send_ack_timer(hpriv_p hpriv);
static void ng_pptpgre_start_recv_ack_timer(hpriv_p hpriv);
+static void ng_pptpgre_start_reorder_timer(hpriv_p hpriv);
static void ng_pptpgre_recv_ack_timeout(node_p node, hook_p hook,
void *arg1, int arg2);
static void ng_pptpgre_send_ack_timeout(node_p node, hook_p hook,
void *arg1, int arg2);
+static void ng_pptpgre_reorder_timeout(node_p node, hook_p hook,
+ void *arg1, int arg2);
static hpriv_p ng_pptpgre_find_session(priv_p privp, u_int16_t cid);
static void ng_pptpgre_reset(hpriv_p hpriv);
static pptptime_t ng_pptpgre_time(void);
+static void ng_pptpgre_ack(const hpriv_p hpriv);
+static int ng_pptpgre_sendq(const hpriv_p hpriv, roqh *q,
+ const struct ng_pptpgre_roq *st);
/* Parse type for struct ng_pptpgre_conf */
static const struct ng_parse_struct_field ng_pptpgre_conf_type_fields[]
@@ -291,6 +331,10 @@ ng_pptpgre_constructor(node_p node)
ng_callout_init(&priv->uppersess.rackTimer);
priv->uppersess.node = node;
+ SLIST_INIT(&priv->uppersess.roq);
+ priv->uppersess.roq_len = 0;
+ ng_callout_init(&priv->uppersess.reorderTimer);
+
for (i = 0; i < SESSHASHSIZE; i++)
LIST_INIT(&priv->sesshash[i]);
@@ -348,6 +392,11 @@ ng_pptpgre_newhook(node_p node, hook_p hook, const char *name)
hpriv->conf.cid = cid;
hpriv->node = node;
hpriv->hook = hook;
+
+ SLIST_INIT(&hpriv->roq);
+ hpriv->roq_len = 0;
+ ng_callout_init(&hpriv->reorderTimer);
+
NG_HOOK_SET_PRIVATE(hook, hpriv);
hash = SESSHASH(cid);
@@ -646,6 +695,49 @@ done:
return (error);
}
+static void
+ng_pptpgre_ack(const hpriv_p hpriv)
+{
+ mtx_assert(&hpriv->mtx, MA_OWNED);
+ if (!(callout_pending(&hpriv->sackTimer))) {
+ /* If delayed ACK is disabled, send it now */
+ if (!hpriv->conf.enableDelayedAck) { /* ack now */
+ ng_pptpgre_xmit(hpriv, NULL);
+ /* ng_pptpgre_xmit() drops the mutex */
+ return;
+ }
+ /* ack later */
+ ng_pptpgre_start_send_ack_timer(hpriv);
+ mtx_unlock(&hpriv->mtx);
+ return;
+ }
+ mtx_unlock(&hpriv->mtx);
+}
+
+/*
+ * Delivers packets from the queue "q" to upper layers. Frees delivered
+ * entries with the exception of one equal to "st" that is allocated
+ * on caller's stack and not on the heap.
+ */
+static int
+ng_pptpgre_sendq(const hpriv_p hpriv, roqh *q, const struct ng_pptpgre_roq *st)
+{
+ struct ng_pptpgre_roq *np;
+ struct mbuf *m;
+ int error = 0;
+
+ mtx_assert(&hpriv->mtx, MA_NOTOWNED);
+ while (!SLIST_EMPTY(q)) {
+ np = SLIST_FIRST(q);
+ SLIST_REMOVE_HEAD(q, next);
+ NGI_GET_M(np->item, m);
+ NG_FWD_NEW_DATA(error, np->item, hpriv->hook, m);
+ if (np != st)
+ free(np, M_NETGRAPH);
+ }
+ return (error);
+}
+
/*
* Handle an incoming packet. The packet includes the IP header.
*/
@@ -661,7 +753,14 @@ ng_pptpgre_rcvdata_lower(hook_p hook, item_p item)
int error = 0;
struct mbuf *m;
- NGI_GET_M(item, m);
+ roqh sendq = SLIST_HEAD_INITIALIZER(sendq); /* send queue on stack */
+ struct ng_pptpgre_roq *last = NULL; /* last packet in the sendq */
+ struct ng_pptpgre_roq *np, *prev;
+ struct ng_pptpgre_roq temp = { { NULL }, NULL, 0 };
+ long diff;
+ u_int32_t seq;
+
+ m = NGI_M(item);
/* Update stats */
priv->stats.recvPackets++;
priv->stats.recvOctets += m->m_pkthdr.len;
@@ -673,18 +772,23 @@ ng_pptpgre_rcvdata_lower(hook_p hook, item_p item)
}
/* Safely pull up the complete IP+GRE headers */
- if (m->m_len < sizeof(*ip) + sizeof(*gre)
- && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
- priv->stats.memoryFailures++;
- ERROUT(ENOBUFS);
+ if (m->m_len < sizeof(*ip) + sizeof(*gre)) {
+ if ((m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
+ priv->stats.memoryFailures++;
+ _NGI_M(item) = NULL;
+ ERROUT(ENOBUFS);
+ }
+ _NGI_M(item) = m;
}
ip = mtod(m, const struct ip *);
iphlen = ip->ip_hl << 2;
if (m->m_len < iphlen + sizeof(*gre)) {
if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
priv->stats.memoryFailures++;
+ _NGI_M(item) = NULL;
ERROUT(ENOBUFS);
}
+ _NGI_M(item) = m;
ip = mtod(m, const struct ip *);
}
gre = (const struct greheader *)((const u_char *)ip + iphlen);
@@ -696,8 +800,10 @@ ng_pptpgre_rcvdata_lower(hook_p hook, item_p item)
if (m->m_len < iphlen + grelen) {
if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
priv->stats.memoryFailures++;
+ _NGI_M(item) = NULL;
ERROUT(ENOBUFS);
}
+ _NGI_M(item) = m;
ip = mtod(m, const struct ip *);
gre = (const struct greheader *)((const u_char *)ip + iphlen);
}
@@ -726,7 +832,6 @@ ng_pptpgre_rcvdata_lower(hook_p hook, item_p item)
const u_int32_t ack = be32dec(&gre->data[gre->hasSeq]);
const int index = ack - hpriv->recvAck - 1;
long sample;
- long diff;
/* Sanity check ack value */
if (PPTP_SEQ_DIFF(ack, hpriv->xmitSeq) > 0) {
@@ -773,54 +878,178 @@ ng_pptpgre_rcvdata_lower(hook_p hook, item_p item)
badAck:
/* See if frame contains any data */
- if (gre->hasSeq) {
- const u_int32_t seq = be32dec(&gre->data[0]);
+ if (!gre->hasSeq) { /* no data to deliver */
+ priv->stats.recvLoneAcks++;
+ mtx_unlock(&hpriv->mtx);
+ ERROUT(0);
+ }
- /* Sanity check sequence number */
- if (PPTP_SEQ_DIFF(seq, hpriv->recvSeq) <= 0) {
- if (seq == hpriv->recvSeq)
- priv->stats.recvDuplicates++;
- else
- priv->stats.recvOutOfOrder++;
+ seq = be32dec(&gre->data[0]);
+
+ diff = PPTP_SEQ_DIFF(seq, hpriv->recvSeq);
+ if (diff <= 0) { /* late or duplicate packet */
+ if (diff < 0 && reorder_max == 0) /* reorder disabled */
+ priv->stats.recvOutOfOrder++; /* late */
+ else
+ priv->stats.recvDuplicates++; /* duplicate */
+ mtx_unlock(&hpriv->mtx);
+ ERROUT(EINVAL);
+ }
+
+ /* Trim mbuf down to internal payload */
+ m_adj(m, iphlen + grelen);
+ if (extralen > 0)
+ m_adj(m, -extralen);
+
+#define INIT_SENDQ(t) do { \
+ t.item = item; \
+ t.seq = seq; \
+ SLIST_INSERT_HEAD(&sendq, &t, next); \
+ last = &t; \
+ hpriv->recvSeq = seq; \
+ goto deliver; \
+ } while(0)
+
+ if (diff == 1)
+ /* the packet came in order, place it at the start of sendq */
+ INIT_SENDQ(temp);
+
+ /* The packet came too early, try to enqueue it.
+ *
+ * Check for duplicate in the queue. After this loop, "prev" will be
+ * NULL if the packet should become new head of the queue,
+ * or else it should be inserted after the "prev".
+ */
+ prev = SLIST_FIRST(&hpriv->roq);
+ SLIST_FOREACH(np, &hpriv->roq, next) {
+ diff = PPTP_SEQ_DIFF(np->seq, seq);
+ if (diff == 0) { /* do not add duplicate, drop it */
+ priv->stats.recvDuplicates++;
mtx_unlock(&hpriv->mtx);
ERROUT(EINVAL);
}
- hpriv->recvSeq = seq;
+ if (diff > 0) { /* we found newer packet */
+ if (np == prev) /* that is the head of the queue */
+ prev = NULL; /* put current packet to the head */
+ break;
+ }
+ prev = np;
+ }
- /* We need to acknowledge this packet; do it soon... */
- if (!(callout_pending(&hpriv->sackTimer))) {
- /* If delayed ACK is disabled, send it now */
- if (!hpriv->conf.enableDelayedAck) { /* ack now */
- ng_pptpgre_xmit(hpriv, NULL);
- /* ng_pptpgre_xmit() drops the mutex */
- } else { /* ack later */
- ng_pptpgre_start_send_ack_timer(hpriv);
- mtx_unlock(&hpriv->mtx);
- }
- } else
- mtx_unlock(&hpriv->mtx);
+ priv->stats.recvOutOfOrder++; /* duplicate not found */
+ if (hpriv->roq_len < reorder_max)
+ goto enqueue; /* reorder enabled and there is a room */
+
+ /*
+ * There is no room in the queue or reorder disabled.
+ *
+ * It the latter case, we may still have non-empty reorder queue
+ * if reorder was disabled in process of reordering.
+ * Then we correctly deliver the queue without growing it.
+ *
+ * In both cases, no malloc()'s until the queue is shortened.
+ */
+ priv->stats.recvReorderOverflow++;
+ if (prev == NULL) { /* new packet goes before the head */
+ INIT_SENDQ(temp); /* of reorder queue, so put it to sendq */
+ }
+#undef INIT_SENDQ
- /* Trim mbuf down to internal payload */
- m_adj(m, iphlen + grelen);
- if (extralen > 0)
- m_adj(m, -extralen);
+ /*
+ * Current packet goes after the head of reorder queue.
+ * Move the head to sendq to make room for current packet.
+ */
+ np = SLIST_FIRST(&hpriv->roq);
+ if (prev == np)
+ prev = NULL;
+ SLIST_REMOVE_HEAD(&hpriv->roq, next);
+ hpriv->roq_len--; /* we are allowed to use malloc() now */
+ SLIST_INSERT_HEAD(&sendq, np, next);
+ last = np;
+ hpriv->recvSeq = np->seq;
- mtx_assert(&hpriv->mtx, MA_NOTOWNED);
+enqueue:
+ np = malloc(sizeof(*np), M_NETGRAPH, M_NOWAIT | M_ZERO);
+ if (np == NULL) {
+ priv->stats.memoryFailures++;
+ /*
+ * Emergency: we cannot save new data.
+ * Flush the queue delivering all queued packets preceeding
+ * current one despite of gaps.
+ */
+ while (!SLIST_EMPTY(&hpriv->roq)) {
+ np = SLIST_FIRST(&hpriv->roq);
+ if (np->seq > seq)
+ break;
+ SLIST_REMOVE_HEAD(&hpriv->roq, next);
+ hpriv->roq_len--;
+ if (last == NULL)
+ SLIST_INSERT_HEAD(&sendq, np, next);
+ else
+ SLIST_INSERT_AFTER(last, np, next);
+ last = np;
+ }
- /* Deliver frame to upper layers */
+ /*
+ * Pretend we got all packets till the current one
+ * and acknowledge it.
+ */
+ hpriv->recvSeq = seq;
+ ng_pptpgre_ack(hpriv); /* drops lock */
+ ng_pptpgre_sendq(hpriv, &sendq, &temp);
NG_FWD_NEW_DATA(error, item, hpriv->hook, m);
+ ERROUT(ENOMEM);
+ }
+
+ /* Add current (early) packet to the reorder queue. */
+ np->item = item;
+ np->seq = seq;
+ if (prev == NULL)
+ SLIST_INSERT_HEAD(&hpriv->roq, np, next);
+ else
+ SLIST_INSERT_AFTER(prev, np, next);
+ hpriv->roq_len++;
+
+deliver:
+ /* Look if we have some packets in sequence after sendq. */
+ while (!SLIST_EMPTY(&hpriv->roq)) {
+ np = SLIST_FIRST(&hpriv->roq);
+ if (PPTP_SEQ_DIFF(np->seq, hpriv->recvSeq) > 1)
+ break; /* the gap in the sequence */
+
+ /* "np" is in sequence, move it to the sendq. */
+ SLIST_REMOVE_HEAD(&hpriv->roq, next);
+ hpriv->roq_len--;
+ hpriv->recvSeq = np->seq;
+
+ if (last == NULL)
+ SLIST_INSERT_HEAD(&sendq, np, next);
+ else
+ SLIST_INSERT_AFTER(last, np, next);
+ last = np;
+ }
+
+ if (SLIST_EMPTY(&hpriv->roq)) {
+ if (callout_pending(&hpriv->reorderTimer))
+ ng_uncallout(&hpriv->reorderTimer, hpriv->node);
} else {
- priv->stats.recvLoneAcks++;
+ if (!callout_pending(&hpriv->reorderTimer))
+ ng_pptpgre_start_reorder_timer(hpriv);
+ }
+
+ if (SLIST_EMPTY(&sendq)) {
+ /* Current packet has been queued, nothing to free/deliver. */
mtx_unlock(&hpriv->mtx);
- NG_FREE_ITEM(item);
- NG_FREE_M(m); /* no data to deliver */
+ return (error);
}
+ /* We need to acknowledge last packet; do it soon... */
+ ng_pptpgre_ack(hpriv); /* drops lock */
+ ng_pptpgre_sendq(hpriv, &sendq, &temp);
return (error);
done:
NG_FREE_ITEM(item);
- NG_FREE_M(m);
return (error);
}
@@ -916,6 +1145,68 @@ ng_pptpgre_send_ack_timeout(node_p node, hook_p hook, void *arg1, int arg2)
mtx_assert(&hpriv->mtx, MA_NOTOWNED);
}
+/*
+ * Start a timer for the reorder queue. This assumes the timer is not
+ * already running.
+ */
+static void
+ng_pptpgre_start_reorder_timer(hpriv_p hpriv)
+{
+ int ticks;
+
+ /* Be conservative: timeout can happen up to 1 tick early */
+ ticks = (((reorder_timeout * hz) + 1000 - 1) / 1000) + 1;
+ ng_callout(&hpriv->reorderTimer, hpriv->node, hpriv->hook,
+ ticks, ng_pptpgre_reorder_timeout, hpriv, 0);
+}
+
+/*
+ * The oldest packet spent too much time in the reorder queue.
+ * Deliver it and next packets in sequence, if any.
+ */
+static void
+ng_pptpgre_reorder_timeout(node_p node, hook_p hook, void *arg1, int arg2)
+{
+ const priv_p priv = NG_NODE_PRIVATE(node);
+ const hpriv_p hpriv = arg1;
+ roqh sendq = SLIST_HEAD_INITIALIZER(sendq);
+ struct ng_pptpgre_roq *np, *last = NULL;
+
+ priv->stats.recvReorderTimeouts++;
+ mtx_lock(&hpriv->mtx);
+ if (SLIST_EMPTY(&hpriv->roq)) { /* should not happen */
+ mtx_unlock(&hpriv->mtx);
+ return;
+ }
+
+ last = np = SLIST_FIRST(&hpriv->roq);
+ hpriv->roq_len--;
+ SLIST_REMOVE_HEAD(&hpriv->roq, next);
+ SLIST_INSERT_HEAD(&sendq, np, next);
+
+ /* Look if we have more packets in sequence */
+ while (!SLIST_EMPTY(&hpriv->roq)) {
+ np = SLIST_FIRST(&hpriv->roq);
+ if (PPTP_SEQ_DIFF(np->seq, last->seq) > 1)
+ break; /* the gap in the sequence */
+
+ /* Next packet is in sequence, move it to the sendq. */
+ hpriv->roq_len--;
+ SLIST_REMOVE_HEAD(&hpriv->roq, next);
+ SLIST_INSERT_AFTER(last, np, next);
+ last = np;
+ }
+
+ hpriv->recvSeq = last->seq;
+ if (!SLIST_EMPTY(&hpriv->roq))
+ ng_pptpgre_start_reorder_timer(hpriv);
+
+ /* We need to acknowledge last packet; do it soon... */
+ ng_pptpgre_ack(hpriv); /* drops lock */
+ ng_pptpgre_sendq(hpriv, &sendq, NULL);
+ mtx_assert(&hpriv->mtx, MA_NOTOWNED);
+}
+
/*************************************************************************
MISC FUNCTIONS
*************************************************************************/
@@ -943,6 +1234,8 @@ ng_pptpgre_find_session(priv_p privp, u_int16_t cid)
static void
ng_pptpgre_reset(hpriv_p hpriv)
{
+ struct ng_pptpgre_roq *np;
+
/* Reset adaptive timeout state */
hpriv->ato = PPTP_MAX_TIMEOUT;
hpriv->rtt = PPTP_TIME_SCALE / 10;
@@ -965,6 +1258,16 @@ ng_pptpgre_reset(hpriv_p hpriv)
/* Stop timers */
ng_uncallout(&hpriv->sackTimer, hpriv->node);
ng_uncallout(&hpriv->rackTimer, hpriv->node);
+ ng_uncallout(&hpriv->reorderTimer, hpriv->node);
+
+ /* Clear reorder queue */
+ while (!SLIST_EMPTY(&hpriv->roq)) {
+ np = SLIST_FIRST(&hpriv->roq);
+ SLIST_REMOVE_HEAD(&hpriv->roq, next);
+ NG_FREE_ITEM(np->item);
+ free(np, M_NETGRAPH);
+ }
+ hpriv->roq_len = 0;
}
/*
diff --git a/sys/netgraph/ng_pptpgre.h b/sys/netgraph/ng_pptpgre.h
index ecba3ce1f37d..08084917dcca 100644
--- a/sys/netgraph/ng_pptpgre.h
+++ b/sys/netgraph/ng_pptpgre.h
@@ -100,6 +100,10 @@ struct ng_pptpgre_stats {
u_int32_t recvLoneAcks; /* ack-only packets rec'd */
u_int32_t recvAckTimeouts; /* times peer failed to ack in time */
u_int32_t memoryFailures; /* times we couldn't allocate memory */
+ u_int32_t recvReorderOverflow; /* times we dropped GRE packet
+ due to overflow of reorder queue */
+ u_int32_t recvReorderTimeouts; /* times we flushed reorder queue
+ due to timeout */
};
/* Keep this in sync with the above structure definition */
@@ -120,6 +124,8 @@ struct ng_pptpgre_stats {
{ "recvLoneAcks", &ng_parse_uint32_type }, \
{ "recvAckTimeouts", &ng_parse_uint32_type }, \
{ "memoryFailures", &ng_parse_uint32_type }, \
+ { "recvReorderOverflow", &ng_parse_uint32_type}, \
+ { "recvReorderTimeouts", &ng_parse_uint32_type}, \
{ NULL } \
}
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index ddf5a4ddfd27..08f40974b07a 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -3733,6 +3733,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
return (0);
}
+#if defined(INET) || defined(INET6)
static struct sctp_tcb *
sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
uint16_t port,
@@ -3822,6 +3823,7 @@ sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
}
return (NULL);
}
+#endif
static struct mbuf *
sctp_add_cookie(struct mbuf *init, int init_offset,
@@ -12699,9 +12701,11 @@ sctp_lower_sosend(struct socket *so,
SCTP_INP_WUNLOCK(inp);
/* With the lock applied look again */
stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL);
+#if defined(INET) || defined(INET6)
if ((stcb == NULL) && (control != NULL) && (port > 0)) {
stcb = sctp_findassociation_cmsgs(&t_inp, port, control, &net, &error);
}
+#endif
if (stcb == NULL) {
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
diff --git a/sys/powerpc/include/atomic.h b/sys/powerpc/include/atomic.h
index 1b3c084db196..c8e1e8447cc7 100644
--- a/sys/powerpc/include/atomic.h
+++ b/sys/powerpc/include/atomic.h
@@ -510,7 +510,7 @@ atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
u_##TYPE v; \
\
v = *p; \
- mb(); \
+ powerpc_lwsync(); \
return (v); \
} \
\
diff --git a/sys/powerpc/include/cpu.h b/sys/powerpc/include/cpu.h
index 3573a0a85d20..00f8437c8c49 100644
--- a/sys/powerpc/include/cpu.h
+++ b/sys/powerpc/include/cpu.h
@@ -128,6 +128,7 @@ get_cyclecount(void)
#define cpu_getstack(td) ((td)->td_frame->fixreg[1])
#define cpu_spinwait() __asm __volatile("or 27,27,27") /* yield */
+#define cpu_lock_delay() DELAY(1)
extern char btext[];
extern char etext[];
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
index a0a97d4af3f2..49e259ad50b9 100644
--- a/sys/powerpc/powerpc/mp_machdep.c
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -100,7 +100,11 @@ machdep_ap_bootstrap(void)
/* Serialize console output and AP count increment */
mtx_lock_spin(&ap_boot_mtx);
ap_awake++;
- printf("SMP: AP CPU #%d launched\n", PCPU_GET(cpuid));
+ if (bootverbose)
+ printf("SMP: AP CPU #%d launched\n", PCPU_GET(cpuid));
+ else
+ printf("%s%d%s", ap_awake == 2 ? "Launching APs: " : "",
+ PCPU_GET(cpuid), ap_awake == mp_ncpus ? "\n" : " ");
mtx_unlock_spin(&ap_boot_mtx);
while(smp_started == 0)
diff --git a/sys/riscv/include/cpu.h b/sys/riscv/include/cpu.h
index 92c5c67ef597..989f8946333d 100644
--- a/sys/riscv/include/cpu.h
+++ b/sys/riscv/include/cpu.h
@@ -46,6 +46,7 @@
#define cpu_getstack(td) ((td)->td_frame->tf_sp)
#define cpu_setstack(td, sp) ((td)->td_frame->tf_sp = (sp))
#define cpu_spinwait() /* nothing */
+#define cpu_lock_delay() DELAY(1)
#ifdef _KERNEL
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index 22bec6355684..0e1299d6509b 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -2098,13 +2098,20 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
new_l3 |= PTE_W;
if ((va >> 63) == 0)
new_l3 |= PTE_U;
- else if (prot & VM_PROT_WRITE)
- new_l3 |= PTE_D;
new_l3 |= (pn << PTE_PPN0_S);
if ((flags & PMAP_ENTER_WIRED) != 0)
new_l3 |= PTE_SW_WIRED;
- if ((m->oflags & VPO_UNMANAGED) == 0)
+
+ /*
+ * Set modified bit gratuitously for writeable mappings if
+ * the page is unmanaged. We do not want to take a fault
+ * to do the dirty bit accounting for these mappings.
+ */
+ if ((m->oflags & VPO_UNMANAGED) != 0) {
+ if (prot & VM_PROT_WRITE)
+ new_l3 |= PTE_D;
+ } else
new_l3 |= PTE_SW_MANAGED;
CTR2(KTR_PMAP, "pmap_enter: %.16lx -> %.16lx", va, pa);
diff --git a/sys/sparc64/include/cpu.h b/sys/sparc64/include/cpu.h
index 54deaf415167..a91159f6a7a2 100644
--- a/sys/sparc64/include/cpu.h
+++ b/sys/sparc64/include/cpu.h
@@ -48,6 +48,7 @@
#define cpu_getstack(td) ((td)->td_frame->tf_sp)
#define cpu_setstack(td, sp) ((td)->td_frame->tf_sp = (sp))
#define cpu_spinwait() /* nothing */
+#define cpu_lock_delay() DELAY(1)
#ifdef _KERNEL
diff --git a/sys/sys/capability.h b/sys/sys/capability.h
index 4b07c090e405..39195e034c56 100644
--- a/sys/sys/capability.h
+++ b/sys/sys/capability.h
@@ -35,7 +35,8 @@
* Historically, the key userspace and kernel Capsicum definitions were found
* in this file. However, it conflicted with POSIX.1e's capability.h, so has
* been renamed capsicum.h. The file remains for backwards compatibility
- * reasons as a nested include.
+ * reasons as a nested include. It is expected to be removed before
+ * FreeBSD 13.
*/
#ifndef _SYS_CAPABILITY_H_
#define _SYS_CAPABILITY_H_
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 93dc23641c7b..94bb6b490b67 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -379,7 +379,8 @@ struct uio;
/*
* From uipc_socket and friends
*/
-int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
+int getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr,
+ size_t len);
int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
struct file **fpp, u_int *fflagp, struct filecaps *havecaps);
void soabort(struct socket *so);
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index 2c5652c7b552..3545745f5a7f 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -243,7 +243,7 @@ int kern_setitimer(struct thread *, u_int, struct itimerval *,
struct itimerval *);
int kern_setrlimit(struct thread *, u_int, struct rlimit *);
int kern_setsockopt(struct thread *td, int s, int level, int name,
- void *optval, enum uio_seg valseg, socklen_t valsize);
+ const void *optval, enum uio_seg valseg, socklen_t valsize);
int kern_settimeofday(struct thread *td, struct timeval *tv,
struct timezone *tzp);
int kern_shm_open(struct thread *td, const char *userpath, int flags,
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index fa54d1234201..a4e12429ebe3 100644
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -99,7 +99,7 @@ struct mount_args {
char type_l_[PADL_(const char *)]; const char * type; char type_r_[PADR_(const char *)];
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
- char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)];
+ char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)];
};
struct unmount_args {
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
@@ -132,7 +132,7 @@ struct sendmsg_args {
};
struct recvfrom_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
char from_l_[PADL_(struct sockaddr *)]; struct sockaddr * from; char from_r_[PADR_(struct sockaddr *)];
@@ -185,7 +185,7 @@ struct getegid_args {
register_t dummy;
};
struct profil_args {
- char samples_l_[PADL_(caddr_t)]; caddr_t samples; char samples_r_[PADR_(caddr_t)];
+ char samples_l_[PADL_(char *)]; char * samples; char samples_r_[PADR_(char *)];
char size_l_[PADL_(size_t)]; size_t size; char size_r_[PADR_(size_t)];
char offset_l_[PADL_(size_t)]; size_t offset; char offset_r_[PADR_(size_t)];
char scale_l_[PADL_(u_int)]; u_int scale; char scale_r_[PADR_(u_int)];
@@ -219,7 +219,7 @@ struct sigaltstack_args {
struct ioctl_args {
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
char com_l_[PADL_(u_long)]; u_long com; char com_r_[PADR_(u_long)];
- char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)];
+ char data_l_[PADL_(char *)]; char * data; char data_r_[PADR_(char *)];
};
struct reboot_args {
char opt_l_[PADL_(int)]; int opt; char opt_r_[PADR_(int)];
@@ -347,7 +347,7 @@ struct socket_args {
};
struct connect_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)];
+ char name_l_[PADL_(const struct sockaddr *)]; const struct sockaddr * name; char name_r_[PADR_(const struct sockaddr *)];
char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)];
};
struct getpriority_args {
@@ -356,14 +356,14 @@ struct getpriority_args {
};
struct bind_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)];
+ char name_l_[PADL_(const struct sockaddr *)]; const struct sockaddr * name; char name_r_[PADR_(const struct sockaddr *)];
char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)];
};
struct setsockopt_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
char level_l_[PADL_(int)]; int level; char level_r_[PADR_(int)];
char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
- char val_l_[PADL_(caddr_t)]; caddr_t val; char val_r_[PADR_(caddr_t)];
+ char val_l_[PADL_(const void *)]; const void * val; char val_r_[PADR_(const void *)];
char valsize_l_[PADL_(int)]; int valsize; char valsize_r_[PADR_(int)];
};
struct listen_args {
@@ -382,7 +382,7 @@ struct getsockopt_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
char level_l_[PADL_(int)]; int level; char level_r_[PADR_(int)];
char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
- char val_l_[PADL_(caddr_t)]; caddr_t val; char val_r_[PADR_(caddr_t)];
+ char val_l_[PADL_(void *)]; void * val; char val_r_[PADR_(void *)];
char avalsize_l_[PADL_(int *)]; int * avalsize; char avalsize_r_[PADR_(int *)];
};
struct readv_args {
@@ -430,10 +430,10 @@ struct mkfifo_args {
};
struct sendto_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)];
+ char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
- char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)];
+ char to_l_[PADL_(const struct sockaddr *)]; const struct sockaddr * to; char to_r_[PADR_(const struct sockaddr *)];
char tolen_l_[PADL_(int)]; int tolen; char tolen_r_[PADR_(int)];
};
struct shutdown_args {
@@ -471,7 +471,7 @@ struct quotactl_args {
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)];
- char arg_l_[PADL_(caddr_t)]; caddr_t arg; char arg_r_[PADR_(caddr_t)];
+ char arg_l_[PADL_(void *)]; void * arg; char arg_r_[PADR_(void *)];
};
struct oquota_args {
register_t dummy;
@@ -484,7 +484,7 @@ struct nlm_syscall_args {
};
struct nfssvc_args {
char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
- char argp_l_[PADL_(caddr_t)]; caddr_t argp; char argp_r_[PADR_(caddr_t)];
+ char argp_l_[PADL_(void *)]; void * argp; char argp_r_[PADR_(void *)];
};
struct lgetfh_args {
char fname_l_[PADL_(const char *)]; const char * fname; char fname_r_[PADR_(const char *)];
@@ -1318,9 +1318,9 @@ struct sctp_peeloff_args {
};
struct sctp_generic_sendmsg_args {
char sd_l_[PADL_(int)]; int sd; char sd_r_[PADR_(int)];
- char msg_l_[PADL_(caddr_t)]; caddr_t msg; char msg_r_[PADR_(caddr_t)];
+ char msg_l_[PADL_(void *)]; void * msg; char msg_r_[PADR_(void *)];
char mlen_l_[PADL_(int)]; int mlen; char mlen_r_[PADR_(int)];
- char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)];
+ char to_l_[PADL_(struct sockaddr *)]; struct sockaddr * to; char to_r_[PADR_(struct sockaddr *)];
char tolen_l_[PADL_(__socklen_t)]; __socklen_t tolen; char tolen_r_[PADR_(__socklen_t)];
char sinfo_l_[PADL_(struct sctp_sndrcvinfo *)]; struct sctp_sndrcvinfo * sinfo; char sinfo_r_[PADR_(struct sctp_sndrcvinfo *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
@@ -1329,7 +1329,7 @@ struct sctp_generic_sendmsg_iov_args {
char sd_l_[PADL_(int)]; int sd; char sd_r_[PADR_(int)];
char iov_l_[PADL_(struct iovec *)]; struct iovec * iov; char iov_r_[PADR_(struct iovec *)];
char iovlen_l_[PADL_(int)]; int iovlen; char iovlen_r_[PADR_(int)];
- char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)];
+ char to_l_[PADL_(struct sockaddr *)]; struct sockaddr * to; char to_r_[PADR_(struct sockaddr *)];
char tolen_l_[PADL_(__socklen_t)]; __socklen_t tolen; char tolen_r_[PADR_(__socklen_t)];
char sinfo_l_[PADL_(struct sctp_sndrcvinfo *)]; struct sctp_sndrcvinfo * sinfo; char sinfo_r_[PADR_(struct sctp_sndrcvinfo *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
@@ -1356,7 +1356,7 @@ struct pwrite_args {
char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)];
};
struct mmap_args {
- char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
@@ -1645,13 +1645,13 @@ struct cap_fcntls_get_args {
struct bindat_args {
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)];
+ char name_l_[PADL_(const struct sockaddr *)]; const struct sockaddr * name; char name_r_[PADR_(const struct sockaddr *)];
char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)];
};
struct connectat_args {
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)];
+ char name_l_[PADL_(const struct sockaddr *)]; const struct sockaddr * name; char name_r_[PADR_(const struct sockaddr *)];
char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)];
};
struct chflagsat_args {
@@ -2207,13 +2207,13 @@ struct sethostname_args {
};
struct osend_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)];
+ char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)];
char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
struct orecv_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
@@ -2245,7 +2245,7 @@ struct orecvmsg_args {
};
struct osendmsg_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
- char msg_l_[PADL_(caddr_t)]; caddr_t msg; char msg_r_[PADR_(caddr_t)];
+ char msg_l_[PADL_(const void *)]; const void * msg; char msg_r_[PADR_(const void *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
struct otruncate_args {
@@ -2258,7 +2258,7 @@ struct oftruncate_args {
};
struct ogetpeername_args {
char fdes_l_[PADL_(int)]; int fdes; char fdes_r_[PADR_(int)];
- char asa_l_[PADL_(caddr_t)]; caddr_t asa; char asa_r_[PADR_(caddr_t)];
+ char asa_l_[PADL_(struct sockaddr *)]; struct sockaddr * asa; char asa_r_[PADR_(struct sockaddr *)];
char alen_l_[PADL_(int *)]; int * alen; char alen_r_[PADR_(int *)];
};
struct osethostid_args {
@@ -2401,7 +2401,7 @@ struct freebsd6_pwrite_args {
char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)];
};
struct freebsd6_mmap_args {
- char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index c85ca559361a..8b458cf115dc 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -133,12 +133,8 @@ struct tty {
void *t_hooksoftc; /* (t) Soft config, for hooks. */
struct cdev *t_dev; /* (c) Primary character device. */
-#ifndef PRINTF_BUFR_SIZE
-#define TTY_PRINTF_SIZE 256
-#else
-#define TTY_PRINTF_SIZE PRINTF_BUFR_SIZE
-#endif
- char t_prbuf[TTY_PRINTF_SIZE]; /* (t) */
+ size_t t_prbufsz; /* (t) SIGINFO buffer size. */
+ char t_prbuf[]; /* (t) SIGINFO buffer. */
};
/*
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 79108ce1ef64..3720ffbee161 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -650,8 +650,8 @@ kmap_alloc_wait(vm_map_t map, vm_size_t size)
map->needs_wakeup = TRUE;
vm_map_unlock_and_wait(map, 0);
}
- vm_map_insert(map, NULL, 0, addr, addr + size, VM_PROT_ALL,
- VM_PROT_ALL, MAP_ACC_CHARGED);
+ vm_map_insert(map, NULL, 0, addr, addr + size, VM_PROT_RW, VM_PROT_RW,
+ MAP_ACC_CHARGED);
vm_map_unlock(map);
return (addr);
}
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 9f592c38410a..c69e5e8bd9d7 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -973,7 +973,7 @@ vm_pageout_laundry_worker(void *arg)
shortfall = 0;
in_shortfall = false;
shortfall_cycle = 0;
- target = 0;
+ last_target = target = 0;
nfreed = 0;
/*
diff --git a/sys/x86/x86/delay.c b/sys/x86/x86/delay.c
index d0900c4330b8..c767250954da 100644
--- a/sys/x86/x86/delay.c
+++ b/sys/x86/x86/delay.c
@@ -51,11 +51,23 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <x86/init.h>
-static u_int
-get_tsc(__unused struct timecounter *tc)
+static void
+delay_tsc(int n)
{
+ uint64_t end, now;
- return (rdtsc32());
+ /*
+ * Pin the current thread ensure correct behavior if the TSCs
+ * on different CPUs are not in sync.
+ */
+ sched_pin();
+ now = rdtsc();
+ end = now + tsc_freq * n / 1000000;
+ do {
+ cpu_spinwait();
+ now = rdtsc();
+ } while (now < end);
+ sched_unpin();
}
static int
@@ -66,22 +78,24 @@ delay_tc(int n)
uint64_t end, freq, now;
u_int last, mask, u;
- tc = timecounter;
- freq = atomic_load_acq_64(&tsc_freq);
- if (tsc_is_invariant && freq != 0) {
- func = get_tsc;
- mask = ~0u;
- } else {
- if (tc->tc_quality <= 0)
- return (0);
- func = tc->tc_get_timecount;
- mask = tc->tc_counter_mask;
- freq = tc->tc_frequency;
+ /*
+ * Only use the TSC if it is P-state invariant. If the TSC is
+ * not P-state invariant and the CPU is not running at the
+ * "full" P-state, then the TSC will increment at some rate
+ * less than tsc_freq and delay_tsc() will wait too long.
+ */
+ if (tsc_is_invariant && tsc_freq != 0) {
+ delay_tsc(n);
+ return (1);
}
+ tc = timecounter;
+ if (tc->tc_quality <= 0)
+ return (0);
+ func = tc->tc_get_timecount;
+ mask = tc->tc_counter_mask;
+ freq = tc->tc_frequency;
now = 0;
end = freq * n / 1000000;
- if (func == get_tsc)
- sched_pin();
last = func(tc) & mask;
do {
cpu_spinwait();
@@ -92,8 +106,6 @@ delay_tc(int n)
now += u - last;
last = u;
} while (now < end);
- if (func == get_tsc)
- sched_unpin();
return (1);
}
@@ -110,3 +122,22 @@ DELAY(int n)
init_ops.early_delay(n);
TSEXIT();
}
+
+void
+cpu_lock_delay(void)
+{
+
+ /*
+ * Use TSC to wait for a usec if present, otherwise fall back
+ * to reading from port 0x84. We can't call into timecounters
+ * for this delay since timecounters might use spin locks.
+ *
+ * Note that unlike delay_tc(), this uses the TSC even if it
+ * is not P-state invariant. For this function it is ok to
+ * wait even a few usecs.
+ */
+ if (tsc_freq != 0)
+ delay_tsc(1);
+ else
+ inb(0x84);
+}