summaryrefslogtreecommitdiff
path: root/sys/compat
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/freebsd32/freebsd32.h15
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c139
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h30
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h5
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c3
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c3
-rw-r--r--sys/compat/freebsd32/freebsd32_systrace_args.c84
-rw-r--r--sys/compat/freebsd32/syscalls.master14
-rw-r--r--sys/compat/linprocfs/linprocfs.c5
-rw-r--r--sys/compat/linux/linux_file.c8
-rw-r--r--sys/compat/linux/linux_stats.c2
-rw-r--r--sys/compat/linuxkpi/common/include/linux/completion.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/device.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/fs.h10
-rw-r--r--sys/compat/linuxkpi/common/include/linux/hrtimer.h79
-rw-r--r--sys/compat/linuxkpi/common/include/linux/io-mapping.h53
-rw-r--r--sys/compat/linuxkpi/common/include/linux/kernel.h3
-rw-r--r--sys/compat/linuxkpi/common/include/linux/kobject.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/kthread.h31
-rw-r--r--sys/compat/linuxkpi/common/include/linux/ktime.h9
-rw-r--r--sys/compat/linuxkpi/common/include/linux/lockdep.h17
-rw-r--r--sys/compat/linuxkpi/common/include/linux/mm.h10
-rw-r--r--sys/compat/linuxkpi/common/include/linux/mm_types.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/module.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/sched.h2
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c7
-rw-r--r--sys/compat/linuxkpi/common/src/linux_current.c3
-rw-r--r--sys/compat/linuxkpi/common/src/linux_hrtimer.c108
-rw-r--r--sys/compat/linuxkpi/common/src/linux_kthread.c59
29 files changed, 576 insertions, 128 deletions
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 05447da3696b..0babcd94f034 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -43,12 +43,12 @@
do { (dst).fld = PTROUT((src).fld); } while (0)
/*
- * Being a newer port, 32-bit FreeBSD/MIPS uses 64-bit time_t.
+ * i386 is the only arch with a 32-bit time_t
*/
-#ifdef __mips__
-typedef int64_t time32_t;
-#else
+#ifdef __amd64__
typedef int32_t time32_t;
+#else
+typedef int64_t time32_t;
#endif
struct timeval32 {
@@ -137,12 +137,13 @@ struct statfs32 {
};
struct kevent32 {
- u_int32_t ident; /* identifier for this event */
+ uint32_t ident; /* identifier for this event */
short filter; /* filter for event */
u_short flags;
u_int fflags;
- int32_t data;
- u_int32_t udata; /* opaque user data identifier */
+ int32_t data1, data2;
+ uint32_t udata; /* opaque user data identifier */
+ uint32_t ext64[8];
};
struct iovec32 {
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 86b5810d2665..c7f0231f6a96 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -109,23 +109,21 @@ __FBSDID("$FreeBSD$");
FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
-#ifndef __mips__
+#ifdef __amd64__
CTASSERT(sizeof(struct timeval32) == 8);
CTASSERT(sizeof(struct timespec32) == 8);
CTASSERT(sizeof(struct itimerval32) == 16);
#endif
CTASSERT(sizeof(struct statfs32) == 256);
-#ifndef __mips__
+#ifdef __amd64__
CTASSERT(sizeof(struct rusage32) == 72);
#endif
CTASSERT(sizeof(struct sigaltstack32) == 12);
-CTASSERT(sizeof(struct kevent32) == 20);
+CTASSERT(sizeof(struct kevent32) == 56);
CTASSERT(sizeof(struct iovec32) == 8);
CTASSERT(sizeof(struct msghdr32) == 28);
#ifdef __amd64__
CTASSERT(sizeof(struct stat32) == 208);
-#endif
-#ifndef __mips__
CTASSERT(sizeof(struct freebsd11_stat32) == 96);
#endif
CTASSERT(sizeof(struct sigaction32) == 24);
@@ -622,7 +620,8 @@ freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
{
struct freebsd32_kevent_args *uap;
struct kevent32 ks32[KQ_NEVENTS];
- int i, error = 0;
+ uint64_t e;
+ int i, j, error;
KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
uap = (struct freebsd32_kevent_args *)arg;
@@ -632,8 +631,24 @@ freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
CP(kevp[i], ks32[i], filter);
CP(kevp[i], ks32[i], flags);
CP(kevp[i], ks32[i], fflags);
- CP(kevp[i], ks32[i], data);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ks32[i].data1 = kevp[i].data;
+ ks32[i].data2 = kevp[i].data >> 32;
+#else
+ ks32[i].data1 = kevp[i].data >> 32;
+ ks32[i].data2 = kevp[i].data;
+#endif
PTROUT_CP(kevp[i], ks32[i], udata);
+ for (j = 0; j < nitems(kevp->ext); j++) {
+ e = kevp[i].ext[j];
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ks32[i].ext64[2 * j] = e;
+ ks32[i].ext64[2 * j + 1] = e >> 32;
+#else
+ ks32[i].ext64[2 * j] = e >> 32;
+ ks32[i].ext64[2 * j + 1] = e;
+#endif
+ }
}
error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
if (error == 0)
@@ -649,7 +664,8 @@ freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
{
struct freebsd32_kevent_args *uap;
struct kevent32 ks32[KQ_NEVENTS];
- int i, error = 0;
+ uint64_t e;
+ int i, j, error;
KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
uap = (struct freebsd32_kevent_args *)arg;
@@ -664,8 +680,20 @@ freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
CP(ks32[i], kevp[i], filter);
CP(ks32[i], kevp[i], flags);
CP(ks32[i], kevp[i], fflags);
- CP(ks32[i], kevp[i], data);
+ kevp[i].data = PAIR32TO64(uint64_t, ks32[i].data);
PTRIN_CP(ks32[i], kevp[i], udata);
+ for (j = 0; j < nitems(kevp->ext); j++) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ e = ks32[i].ext64[2 * j + 1];
+ e <<= 32;
+ e += ks32[i].ext64[2 * j];
+#else
+ e = ks32[i].ext64[2 * j];
+ e <<= 32;
+ e += ks32[i].ext64[2 * j + 1];
+#endif
+ kevp[i].ext[j] = e;
+ }
}
done:
return (error);
@@ -683,6 +711,98 @@ freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
};
int error;
+ if (uap->timeout) {
+ error = copyin(uap->timeout, &ts32, sizeof(ts32));
+ if (error)
+ return (error);
+ CP(ts32, ts, tv_sec);
+ CP(ts32, ts, tv_nsec);
+ tsp = &ts;
+ } else
+ tsp = NULL;
+ error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
+ &k_ops, tsp);
+ return (error);
+}
+
+#ifdef COMPAT_FREEBSD11
+struct kevent32_freebsd11 {
+ u_int32_t ident; /* identifier for this event */
+ short filter; /* filter for event */
+ u_short flags;
+ u_int fflags;
+ int32_t data;
+ u_int32_t udata; /* opaque user data identifier */
+};
+
+static int
+freebsd32_kevent11_copyout(void *arg, struct kevent *kevp, int count)
+{
+ struct freebsd11_freebsd32_kevent_args *uap;
+ struct kevent32_freebsd11 ks32[KQ_NEVENTS];
+ int i, error;
+
+ KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
+ uap = (struct freebsd11_freebsd32_kevent_args *)arg;
+
+ for (i = 0; i < count; i++) {
+ CP(kevp[i], ks32[i], ident);
+ CP(kevp[i], ks32[i], filter);
+ CP(kevp[i], ks32[i], flags);
+ CP(kevp[i], ks32[i], fflags);
+ CP(kevp[i], ks32[i], data);
+ PTROUT_CP(kevp[i], ks32[i], udata);
+ }
+ error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
+ if (error == 0)
+ uap->eventlist += count;
+ return (error);
+}
+
+/*
+ * Copy 'count' items from the list pointed to by uap->changelist.
+ */
+static int
+freebsd32_kevent11_copyin(void *arg, struct kevent *kevp, int count)
+{
+ struct freebsd11_freebsd32_kevent_args *uap;
+ struct kevent32_freebsd11 ks32[KQ_NEVENTS];
+ int i, j, error;
+
+ KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
+ uap = (struct freebsd11_freebsd32_kevent_args *)arg;
+
+ error = copyin(uap->changelist, ks32, count * sizeof *ks32);
+ if (error)
+ goto done;
+ uap->changelist += count;
+
+ for (i = 0; i < count; i++) {
+ CP(ks32[i], kevp[i], ident);
+ CP(ks32[i], kevp[i], filter);
+ CP(ks32[i], kevp[i], flags);
+ CP(ks32[i], kevp[i], fflags);
+ CP(ks32[i], kevp[i], data);
+ PTRIN_CP(ks32[i], kevp[i], udata);
+ for (j = 0; j < nitems(kevp->ext); j++)
+ kevp[i].ext[j] = 0;
+ }
+done:
+ return (error);
+}
+
+int
+freebsd11_freebsd32_kevent(struct thread *td,
+ struct freebsd11_freebsd32_kevent_args *uap)
+{
+ struct timespec32 ts32;
+ struct timespec ts, *tsp;
+ struct kevent_copyops k_ops = {
+ .arg = uap,
+ .k_copyout = freebsd32_kevent11_copyout,
+ .k_copyin = freebsd32_kevent11_copyin,
+ };
+ int error;
if (uap->timeout) {
error = copyin(uap->timeout, &ts32, sizeof(ts32));
@@ -697,6 +817,7 @@ freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
&k_ops, tsp);
return (error);
}
+#endif
int
freebsd32_gettimeofday(struct thread *td,
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
index c133ae4919ff..9710e5735252 100644
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -294,14 +294,6 @@ struct freebsd32_aio_waitcomplete_args {
char aiocbp_l_[PADL_(struct aiocb32 **)]; struct aiocb32 ** aiocbp; char aiocbp_r_[PADR_(struct aiocb32 **)];
char timeout_l_[PADL_(struct timespec32 *)]; struct timespec32 * timeout; char timeout_r_[PADR_(struct timespec32 *)];
};
-struct freebsd32_kevent_args {
- char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
- char changelist_l_[PADL_(const struct kevent32 *)]; const struct kevent32 * changelist; char changelist_r_[PADR_(const struct kevent32 *)];
- char nchanges_l_[PADL_(int)]; int nchanges; char nchanges_r_[PADR_(int)];
- char eventlist_l_[PADL_(struct kevent32 *)]; struct kevent32 * eventlist; char eventlist_r_[PADR_(struct kevent32 *)];
- char nevents_l_[PADL_(int)]; int nevents; char nevents_r_[PADR_(int)];
- char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
-};
struct freebsd32_nmount_args {
char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
char iovcnt_l_[PADL_(unsigned int)]; unsigned int iovcnt; char iovcnt_r_[PADR_(unsigned int)];
@@ -693,6 +685,14 @@ struct freebsd32_getdirentries_args {
char count_l_[PADL_(size_t)]; size_t count; char count_r_[PADR_(size_t)];
char basep_l_[PADL_(int32_t *)]; int32_t * basep; char basep_r_[PADR_(int32_t *)];
};
+struct freebsd32_kevent_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char changelist_l_[PADL_(const struct kevent32 *)]; const struct kevent32 * changelist; char changelist_r_[PADR_(const struct kevent32 *)];
+ char nchanges_l_[PADL_(int)]; int nchanges; char nchanges_r_[PADR_(int)];
+ char eventlist_l_[PADL_(struct kevent32 *)]; struct kevent32 * eventlist; char eventlist_r_[PADR_(struct kevent32 *)];
+ char nevents_l_[PADL_(int)]; int nevents; char nevents_r_[PADR_(int)];
+ char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
+};
#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
@@ -747,7 +747,6 @@ int freebsd32_jail(struct thread *, struct freebsd32_jail_args *);
int freebsd32_sigtimedwait(struct thread *, struct freebsd32_sigtimedwait_args *);
int freebsd32_sigwaitinfo(struct thread *, struct freebsd32_sigwaitinfo_args *);
int freebsd32_aio_waitcomplete(struct thread *, struct freebsd32_aio_waitcomplete_args *);
-int freebsd32_kevent(struct thread *, struct freebsd32_kevent_args *);
int freebsd32_nmount(struct thread *, struct freebsd32_nmount_args *);
int freebsd32_sendfile(struct thread *, struct freebsd32_sendfile_args *);
int freebsd32_ksem_init(struct thread *, struct freebsd32_ksem_init_args *);
@@ -823,6 +822,7 @@ int freebsd32_fstat(struct thread *, struct freebsd32_fstat_args *);
int freebsd32_fstatat(struct thread *, struct freebsd32_fstatat_args *);
int freebsd32_fhstat(struct thread *, struct freebsd32_fhstat_args *);
int freebsd32_getdirentries(struct thread *, struct freebsd32_getdirentries_args *);
+int freebsd32_kevent(struct thread *, struct freebsd32_kevent_args *);
#ifdef COMPAT_43
@@ -1165,6 +1165,14 @@ struct freebsd11_freebsd32_fhstat_args {
char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)];
char sb_l_[PADL_(struct freebsd11_stat32 *)]; struct freebsd11_stat32 * sb; char sb_r_[PADR_(struct freebsd11_stat32 *)];
};
+struct freebsd11_freebsd32_kevent_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char changelist_l_[PADL_(const struct kevent32_freebsd11 *)]; const struct kevent32_freebsd11 * changelist; char changelist_r_[PADR_(const struct kevent32_freebsd11 *)];
+ char nchanges_l_[PADL_(int)]; int nchanges; char nchanges_r_[PADR_(int)];
+ char eventlist_l_[PADL_(struct kevent32_freebsd11 *)]; struct kevent32_freebsd11 * eventlist; char eventlist_r_[PADR_(struct kevent32_freebsd11 *)];
+ char nevents_l_[PADL_(int)]; int nevents; char nevents_r_[PADR_(int)];
+ char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
+};
#ifdef PAD64_REQUIRED
#else
#endif
@@ -1196,6 +1204,7 @@ int freebsd11_freebsd32_lstat(struct thread *, struct freebsd11_freebsd32_lstat_
int freebsd11_freebsd32_getdirentries(struct thread *, struct freebsd11_freebsd32_getdirentries_args *);
int freebsd11_freebsd32_getdents(struct thread *, struct freebsd11_freebsd32_getdents_args *);
int freebsd11_freebsd32_fhstat(struct thread *, struct freebsd11_freebsd32_fhstat_args *);
+int freebsd11_freebsd32_kevent(struct thread *, struct freebsd11_freebsd32_kevent_args *);
int freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fstatat_args *);
int freebsd11_freebsd32_mknodat(struct thread *, struct freebsd11_freebsd32_mknodat_args *);
@@ -1294,7 +1303,7 @@ int freebsd11_freebsd32_mknodat(struct thread *, struct freebsd11_freebsd32_mkno
#define FREEBSD32_SYS_AUE_freebsd32_sigtimedwait AUE_SIGWAIT
#define FREEBSD32_SYS_AUE_freebsd32_sigwaitinfo AUE_NULL
#define FREEBSD32_SYS_AUE_freebsd32_aio_waitcomplete AUE_AIO_WAITCOMPLETE
-#define FREEBSD32_SYS_AUE_freebsd32_kevent AUE_KEVENT
+#define FREEBSD32_SYS_AUE_freebsd11_freebsd32_kevent AUE_KEVENT
#define FREEBSD32_SYS_AUE_freebsd32_nmount AUE_NMOUNT
#define FREEBSD32_SYS_AUE_freebsd32_sendfile AUE_SENDFILE
#define FREEBSD32_SYS_AUE_freebsd32_ksem_init AUE_SEMINIT
@@ -1360,6 +1369,7 @@ int freebsd11_freebsd32_mknodat(struct thread *, struct freebsd11_freebsd32_mkno
#define FREEBSD32_SYS_AUE_freebsd32_fstatat AUE_FSTATAT
#define FREEBSD32_SYS_AUE_freebsd32_fhstat AUE_FHSTAT
#define FREEBSD32_SYS_AUE_freebsd32_getdirentries AUE_GETDIRENTRIES
+#define FREEBSD32_SYS_AUE_freebsd32_kevent AUE_KEVENT
#undef PAD_
#undef PADL_
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
index 3a93b654e7c5..4818ada6051d 100644
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -299,7 +299,7 @@
#define FREEBSD32_SYS_getresuid 360
#define FREEBSD32_SYS_getresgid 361
#define FREEBSD32_SYS_kqueue 362
-#define FREEBSD32_SYS_freebsd32_kevent 363
+#define FREEBSD32_SYS_freebsd11_freebsd32_kevent 363
#define FREEBSD32_SYS_extattr_set_fd 371
#define FREEBSD32_SYS_extattr_get_fd 372
#define FREEBSD32_SYS_extattr_delete_fd 373
@@ -467,4 +467,5 @@
#define FREEBSD32_SYS_getfsstat 557
#define FREEBSD32_SYS_fhstatfs 558
#define FREEBSD32_SYS_mknodat 559
-#define FREEBSD32_SYS_MAXSYSCALL 560
+#define FREEBSD32_SYS_freebsd32_kevent 560
+#define FREEBSD32_SYS_MAXSYSCALL 561
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
index 10166d3930a2..6588321af1a5 100644
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -372,7 +372,7 @@ const char *freebsd32_syscallnames[] = {
"getresuid", /* 360 = getresuid */
"getresgid", /* 361 = getresgid */
"kqueue", /* 362 = kqueue */
- "freebsd32_kevent", /* 363 = freebsd32_kevent */
+ "compat11.freebsd32_kevent", /* 363 = freebsd11 freebsd32_kevent */
"#364", /* 364 = __cap_get_proc */
"#365", /* 365 = __cap_set_proc */
"#366", /* 366 = __cap_get_fd */
@@ -592,4 +592,5 @@ const char *freebsd32_syscallnames[] = {
"getfsstat", /* 557 = getfsstat */
"fhstatfs", /* 558 = fhstatfs */
"mknodat", /* 559 = mknodat */
+ "freebsd32_kevent", /* 560 = freebsd32_kevent */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index ffb99932e7b5..ee7d6c763d0b 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -421,7 +421,7 @@ struct sysent freebsd32_sysent[] = {
{ AS(getresuid_args), (sy_call_t *)sys_getresuid, AUE_GETRESUID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 360 = getresuid */
{ AS(getresgid_args), (sy_call_t *)sys_getresgid, AUE_GETRESGID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 361 = getresgid */
{ 0, (sy_call_t *)sys_kqueue, AUE_KQUEUE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 362 = kqueue */
- { AS(freebsd32_kevent_args), (sy_call_t *)freebsd32_kevent, AUE_KEVENT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 363 = freebsd32_kevent */
+ { compat11(AS(freebsd11_freebsd32_kevent_args),freebsd32_kevent), AUE_KEVENT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 363 = freebsd11 freebsd32_kevent */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 364 = __cap_get_proc */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 365 = __cap_set_proc */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 366 = __cap_get_fd */
@@ -641,4 +641,5 @@ struct sysent freebsd32_sysent[] = {
{ AS(getfsstat_args), (sy_call_t *)sys_getfsstat, AUE_GETFSSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 557 = getfsstat */
{ AS(fhstatfs_args), (sy_call_t *)sys_fhstatfs, AUE_FHSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 558 = fhstatfs */
{ AS(mknodat_args), (sy_call_t *)sys_mknodat, AUE_MKNODAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 559 = mknodat */
+ { AS(freebsd32_kevent_args), (sy_call_t *)freebsd32_kevent, AUE_KEVENT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 560 = freebsd32_kevent */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
index b85ce2b498ff..2303788d6c04 100644
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -1774,18 +1774,6 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
*n_args = 0;
break;
}
- /* freebsd32_kevent */
- case 363: {
- struct freebsd32_kevent_args *p = params;
- iarg[0] = p->fd; /* int */
- uarg[1] = (intptr_t) p->changelist; /* const struct kevent32 * */
- iarg[2] = p->nchanges; /* int */
- uarg[3] = (intptr_t) p->eventlist; /* struct kevent32 * */
- iarg[4] = p->nevents; /* int */
- uarg[5] = (intptr_t) p->timeout; /* const struct timespec32 * */
- *n_args = 6;
- break;
- }
/* extattr_set_fd */
case 371: {
struct extattr_set_fd_args *p = params;
@@ -3266,6 +3254,18 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
*n_args = 4;
break;
}
+ /* freebsd32_kevent */
+ case 560: {
+ struct freebsd32_kevent_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->changelist; /* const struct kevent32 * */
+ iarg[2] = p->nchanges; /* int */
+ uarg[3] = (intptr_t) p->eventlist; /* struct kevent32 * */
+ iarg[4] = p->nevents; /* int */
+ uarg[5] = (intptr_t) p->timeout; /* const struct timespec32 * */
+ *n_args = 6;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -6088,31 +6088,6 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* kqueue */
case 362:
break;
- /* freebsd32_kevent */
- case 363:
- switch(ndx) {
- case 0:
- p = "int";
- break;
- case 1:
- p = "userland const struct kevent32 *";
- break;
- case 2:
- p = "int";
- break;
- case 3:
- p = "userland struct kevent32 *";
- break;
- case 4:
- p = "int";
- break;
- case 5:
- p = "userland const struct timespec32 *";
- break;
- default:
- break;
- };
- break;
/* extattr_set_fd */
case 371:
switch(ndx) {
@@ -8768,6 +8743,31 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
};
break;
+ /* freebsd32_kevent */
+ case 560:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "userland const struct kevent32 *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland struct kevent32 *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ case 5:
+ p = "userland const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -9805,11 +9805,6 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* kqueue */
case 362:
- /* freebsd32_kevent */
- case 363:
- if (ndx == 0 || ndx == 1)
- p = "int";
- break;
/* extattr_set_fd */
case 371:
if (ndx == 0 || ndx == 1)
@@ -10619,6 +10614,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* freebsd32_kevent */
+ case 560:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index fce75fe3488a..41efe33a5d1e 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -667,10 +667,12 @@
361 AUE_GETRESGID NOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \
gid_t *sgid); }
362 AUE_KQUEUE NOPROTO { int kqueue(void); }
-363 AUE_KEVENT STD { int freebsd32_kevent(int fd, \
- const struct kevent32 *changelist, \
+363 AUE_KEVENT COMPAT11 { int freebsd32_kevent(int fd, \
+ const struct kevent32_freebsd11 * \
+ changelist, \
int nchanges, \
- struct kevent32 *eventlist, int nevents, \
+ struct kevent32_freebsd11 *eventlist, \
+ int nevents, \
const struct timespec32 *timeout); }
364 AUE_NULL UNIMPL __cap_get_proc
365 AUE_NULL UNIMPL __cap_set_proc
@@ -1111,3 +1113,9 @@
struct statfs32 *buf); }
559 AUE_MKNODAT NOPROTO { int mknodat(int fd, char *path, mode_t mode, \
dev_t dev); }
+560 AUE_KEVENT STD { int freebsd32_kevent(int fd, \
+ const struct kevent32 *changelist, \
+ int nchanges, \
+ struct kevent32 *eventlist, \
+ int nevents, \
+ const struct timespec32 *timeout); }
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 57853e6385c1..b707a18d3e87 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -245,7 +245,10 @@ linprocfs_docpuinfo(PFS_FILL_ARGS)
break;
}
#endif
- do_cpuid(0x80000006, cache_size);
+ if (cpu_exthigh >= 0x80000006)
+ do_cpuid(0x80000006, cache_size);
+ else
+ memset(cache_size, 0, sizeof(cache_size));
for (i = 0; i < mp_ncpus; ++i) {
fqmhz = 0;
fqkhz = 0;
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index f4926873136e..c66c37e0ccfa 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -381,9 +381,9 @@ linux_getdents(struct thread *td, struct linux_getdents_args *args)
td->td_retval[0] = retval;
out:
- free(lbuf, M_LINUX);
+ free(lbuf, M_TEMP);
out1:
- free(buf, M_LINUX);
+ free(buf, M_TEMP);
return (error);
}
@@ -507,9 +507,9 @@ linux_readdir(struct thread *td, struct linux_readdir_args *args)
if (error == 0)
td->td_retval[0] = linuxreclen;
- free(lbuf, M_LINUX);
+ free(lbuf, M_TEMP);
out:
- free(buf, M_LINUX);
+ free(buf, M_TEMP);
return (error);
}
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index 533d77193aa8..5bd2963507c4 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -318,6 +318,7 @@ struct l_statfs {
#define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
#define LINUX_PROC_SUPER_MAGIC 0x9fa0L
#define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
+#define LINUX_ZFS_SUPER_MAGIC 0x2FC12FC1
#define LINUX_DEVFS_SUPER_MAGIC 0x1373L
#define LINUX_SHMFS_MAGIC 0x01021994
@@ -327,6 +328,7 @@ bsd_to_linux_ftype(const char *fstypename)
int i;
static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
{"ufs", LINUX_UFS_SUPER_MAGIC},
+ {"zfs", LINUX_ZFS_SUPER_MAGIC},
{"cd9660", LINUX_ISOFS_SUPER_MAGIC},
{"nfs", LINUX_NFS_SUPER_MAGIC},
{"ext2fs", LINUX_EXT2_SUPER_MAGIC},
diff --git a/sys/compat/linuxkpi/common/include/linux/completion.h b/sys/compat/linuxkpi/common/include/linux/completion.h
index 73c1a99dfc44..92ccc61f38da 100644
--- a/sys/compat/linuxkpi/common/include/linux/completion.h
+++ b/sys/compat/linuxkpi/common/include/linux/completion.h
@@ -32,7 +32,6 @@
#define _LINUX_COMPLETION_H_
#include <linux/errno.h>
-#include <linux/wait.h>
struct completion {
unsigned int done;
diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h
index af69fa05e2e6..f868c32d5656 100644
--- a/sys/compat/linuxkpi/common/include/linux/device.h
+++ b/sys/compat/linuxkpi/common/include/linux/device.h
@@ -69,6 +69,7 @@ struct dev_pm_ops {
int (*freeze)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw)(struct device *dev);
+ int (*thaw_early)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore)(struct device *dev);
diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h
index cc475ba2807e..ef5d1cc265e1 100644
--- a/sys/compat/linuxkpi/common/include/linux/fs.h
+++ b/sys/compat/linuxkpi/common/include/linux/fs.h
@@ -261,7 +261,15 @@ iput(struct inode *inode)
static inline loff_t
no_llseek(struct file *file, loff_t offset, int whence)
{
- return -ESPIPE;
+
+ return (-ESPIPE);
+}
+
+static inline loff_t
+noop_llseek(struct linux_file *file, loff_t offset, int whence)
+{
+
+ return (file->_file->f_offset);
}
#endif /* _LINUX_FS_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/hrtimer.h b/sys/compat/linuxkpi/common/include/linux/hrtimer.h
new file mode 100644
index 000000000000..658a5407771e
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/hrtimer.h
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_HRTIMER_H_
+#define _LINUX_HRTIMER_H_
+
+#include <sys/_callout.h>
+#include <sys/_mutex.h>
+
+#include <linux/ktime.h>
+#include <linux/timer.h>
+
+enum hrtimer_mode {
+ HRTIMER_MODE_REL,
+};
+
+enum hrtimer_restart {
+ HRTIMER_RESTART,
+ HRTIMER_NORESTART,
+};
+
+struct hrtimer {
+ enum hrtimer_restart (*function)(struct hrtimer *);
+ struct mtx mtx;
+ struct callout callout;
+ uint32_t flags;
+};
+
+#define hrtimer_active(hrtimer) linux_hrtimer_active(hrtimer)
+#define hrtimer_cancel(hrtimer) linux_hrtimer_cancel(hrtimer)
+#define hrtimer_init(hrtimer, clock, mode) do { \
+ CTASSERT((clock) == CLOCK_MONOTONIC); \
+ CTASSERT((mode) == HRTIMER_MODE_REL); \
+ linux_hrtimer_init(hrtimer); \
+} while (0)
+#define hrtimer_set_expires(hrtimer, time) \
+ linux_hrtimer_set_expires(hrtimer, time)
+#define hrtimer_start(hrtimer, time, mode) do { \
+ CTASSERT((mode) == HRTIMER_MODE_REL); \
+ linux_hrtimer_start(hrtimer, time); \
+} while (0)
+#define hrtimer_start_range_ns(hrtimer, time, prec, mode) do { \
+ CTASSERT((mode) == HRTIMER_MODE_REL); \
+ linux_hrtimer_start_range_ns(hrtimer, time, prec); \
+} while (0)
+
+bool linux_hrtimer_active(struct hrtimer *);
+int linux_hrtimer_cancel(struct hrtimer *);
+void linux_hrtimer_init(struct hrtimer *);
+void linux_hrtimer_set_expires(struct hrtimer *, ktime_t);
+void linux_hrtimer_start(struct hrtimer *, ktime_t);
+void linux_hrtimer_start_range_ns(struct hrtimer *, ktime_t, int64_t);
+
+#endif /* _LINUX_HRTIMER_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/io-mapping.h b/sys/compat/linuxkpi/common/include/linux/io-mapping.h
index 8650dba65e6b..7c92c50d637a 100644
--- a/sys/compat/linuxkpi/common/include/linux/io-mapping.h
+++ b/sys/compat/linuxkpi/common/include/linux/io-mapping.h
@@ -28,52 +28,85 @@
*
* $FreeBSD$
*/
-#ifndef _LINUX_IO_MAPPING_H_
+
+#ifndef _LINUX_IO_MAPPING_H_
#define _LINUX_IO_MAPPING_H_
+#include <sys/types.h>
+#include <machine/vm.h>
+
#include <linux/types.h>
#include <linux/io.h>
+#include <linux/slab.h>
-struct io_mapping;
+struct io_mapping {
+ unsigned long base;
+ unsigned long size;
+ void *mem;
+ vm_memattr_t attr;
+};
+
+static inline struct io_mapping *
+io_mapping_init_wc(struct io_mapping *mapping, resource_size_t base,
+ unsigned long size)
+{
+
+ mapping->base = base;
+ mapping->size = size;
+ mapping->mem = ioremap_wc(base, size);
+ mapping->attr = VM_MEMATTR_WRITE_COMBINING;
+ return (mapping);
+}
static inline struct io_mapping *
io_mapping_create_wc(resource_size_t base, unsigned long size)
{
+ struct io_mapping *mapping;
- return ioremap_wc(base, size);
+ mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
+ if (mapping == NULL)
+ return (NULL);
+ return (io_mapping_init_wc(mapping, base, size));
+}
+
+static inline void
+io_mapping_fini(struct io_mapping *mapping)
+{
+
+ iounmap(mapping->mem);
}
static inline void
io_mapping_free(struct io_mapping *mapping)
{
- iounmap(mapping);
+ io_mapping_fini(mapping->mem);
+ kfree(mapping);
}
static inline void *
io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
{
- return (((char *)mapping) + offset);
+ return ((char *)mapping->mem + offset);
}
static inline void
io_mapping_unmap_atomic(void *vaddr)
{
-
}
static inline void *
-io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
+io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset,
+ unsigned long size)
{
- return (((char *) mapping) + offset);
+ return ((char *)mapping->mem + offset);
}
static inline void
io_mapping_unmap(void *vaddr)
{
-
}
-#endif /* _LINUX_IO_MAPPING_H_ */
+#endif /* _LINUX_IO_MAPPING_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/kernel.h b/sys/compat/linuxkpi/common/include/linux/kernel.h
index 3631ba5f2428..c2641320871c 100644
--- a/sys/compat/linuxkpi/common/include/linux/kernel.h
+++ b/sys/compat/linuxkpi/common/include/linux/kernel.h
@@ -49,7 +49,6 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/jiffies.h>
-#include <linux/wait.h>
#include <linux/log2.h>
#include <asm/byteorder.h>
@@ -261,6 +260,8 @@ scnprintf(char *buf, size_t size, const char *fmt, ...)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define u64_to_user_ptr(val) ((void *)(uintptr_t)(val))
+
static inline unsigned long long
simple_strtoull(const char *cp, char **endp, unsigned int base)
{
diff --git a/sys/compat/linuxkpi/common/include/linux/kobject.h b/sys/compat/linuxkpi/common/include/linux/kobject.h
index a000c4eebc10..261f35539469 100644
--- a/sys/compat/linuxkpi/common/include/linux/kobject.h
+++ b/sys/compat/linuxkpi/common/include/linux/kobject.h
@@ -35,6 +35,7 @@
#include <linux/kernel.h>
#include <linux/kref.h>
+#include <linux/list.h>
#include <linux/slab.h>
struct kobject;
diff --git a/sys/compat/linuxkpi/common/include/linux/kthread.h b/sys/compat/linuxkpi/common/include/linux/kthread.h
index 8c7e3c899829..3afd21dc9356 100644
--- a/sys/compat/linuxkpi/common/include/linux/kthread.h
+++ b/sys/compat/linuxkpi/common/include/linux/kthread.h
@@ -48,15 +48,26 @@
__task; \
})
-#define in_atomic() ({ \
- linux_in_atomic(); \
-})
+int linux_kthread_stop(struct task_struct *);
+bool linux_kthread_should_stop_task(struct task_struct *);
+bool linux_kthread_should_stop(void);
+int linux_kthread_park(struct task_struct *);
+void linux_kthread_parkme(void);
+bool linux_kthread_should_park(void);
+void linux_kthread_unpark(struct task_struct *);
+void linux_kthread_fn(void *);
+struct task_struct *linux_kthread_setup_and_run(struct thread *,
+ linux_task_fn_t *, void *arg);
+int linux_in_atomic(void);
+
+#define kthread_stop(task) linux_kthread_stop(task)
+#define kthread_should_stop() linux_kthread_should_stop()
+#define kthread_should_stop_task(task) linux_kthread_should_stop_task(task)
+#define kthread_park(task) linux_kthread_park(task)
+#define kthread_parkme() linux_kthread_parkme()
+#define kthread_should_park() linux_kthread_should_park()
+#define kthread_unpark(task) linux_kthread_unpark(task)
-extern int kthread_stop(struct task_struct *);
-extern bool kthread_should_stop_task(struct task_struct *);
-extern bool kthread_should_stop(void);
-extern void linux_kthread_fn(void *);
-extern struct task_struct *linux_kthread_setup_and_run(struct thread *, linux_task_fn_t *, void *arg);
-extern int linux_in_atomic(void);
+#define in_atomic() linux_in_atomic()
-#endif /* _LINUX_KTHREAD_H_ */
+#endif /* _LINUX_KTHREAD_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/ktime.h b/sys/compat/linuxkpi/common/include/linux/ktime.h
index 7c6c40fe1a8e..e2fd977a7cc5 100644
--- a/sys/compat/linuxkpi/common/include/linux/ktime.h
+++ b/sys/compat/linuxkpi/common/include/linux/ktime.h
@@ -51,6 +51,15 @@ ktime_to_ns(ktime_t kt)
return kt.tv64;
}
+static inline ktime_t
+ns_to_ktime(uint64_t nsec)
+{
+ ktime_t kt;
+
+ kt.tv64 = nsec;
+ return (kt);
+}
+
static inline int64_t
ktime_divns(const ktime_t kt, int64_t div)
{
diff --git a/sys/compat/linuxkpi/common/include/linux/lockdep.h b/sys/compat/linuxkpi/common/include/linux/lockdep.h
index 27386935bbe6..ef562e300cd9 100644
--- a/sys/compat/linuxkpi/common/include/linux/lockdep.h
+++ b/sys/compat/linuxkpi/common/include/linux/lockdep.h
@@ -28,14 +28,23 @@
*
* $FreeBSD$
*/
-#ifndef _LINUX_LOCKDEP_H_
+
+#ifndef _LINUX_LOCKDEP_H_
#define _LINUX_LOCKDEP_H_
struct lock_class_key {
};
-#define lockdep_set_class(lock, key)
+#define lockdep_set_class(lock, key)
+
+#define lockdep_set_class_and_name(lock, key, name)
+
+#define lockdep_assert_held(m) \
+ sx_assert(&(m)->sx, SA_XLOCKED)
+
+#define lockdep_assert_held_once(m) \
+ sx_assert(&(m)->sx, SA_XLOCKED | SA_NOTRECURSED)
-#define lockdep_set_class_and_name(lock, key, name)
+#define lockdep_is_held(m) (sx_xholder(&(m)->sx) == curthread)
-#endif /* _LINUX_LOCKDEP_H_ */
+#endif /* _LINUX_LOCKDEP_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/mm.h b/sys/compat/linuxkpi/common/include/linux/mm.h
index 6f67a0ba4b41..c2ccb4cb96ad 100644
--- a/sys/compat/linuxkpi/common/include/linux/mm.h
+++ b/sys/compat/linuxkpi/common/include/linux/mm.h
@@ -257,16 +257,6 @@ vm_get_page_prot(unsigned long vm_flags)
return (vm_flags & VM_PROT_ALL);
}
-extern int vm_insert_mixed(struct vm_area_struct *, unsigned long addr, pfn_t pfn);
-
-extern int
-vm_insert_pfn(struct vm_area_struct *, unsigned long addr,
- unsigned long pfn);
-
-extern int
-vm_insert_pfn_prot(struct vm_area_struct *, unsigned long addr,
- unsigned long pfn, pgprot_t pgprot);
-
static inline vm_page_t
vmalloc_to_page(const void *addr)
{
diff --git a/sys/compat/linuxkpi/common/include/linux/mm_types.h b/sys/compat/linuxkpi/common/include/linux/mm_types.h
index 6b13dfd9b62c..44aad34c9ba2 100644
--- a/sys/compat/linuxkpi/common/include/linux/mm_types.h
+++ b/sys/compat/linuxkpi/common/include/linux/mm_types.h
@@ -30,7 +30,6 @@
#define _LINUX_MM_TYPES_H_
#include <linux/types.h>
-#include <linux/list.h>
#include <linux/page.h>
#include <linux/rwsem.h>
diff --git a/sys/compat/linuxkpi/common/include/linux/module.h b/sys/compat/linuxkpi/common/include/linux/module.h
index 59c30a7ab77c..13e5e0012d82 100644
--- a/sys/compat/linuxkpi/common/include/linux/module.h
+++ b/sys/compat/linuxkpi/common/include/linux/module.h
@@ -37,6 +37,7 @@
#include <linux/list.h>
#include <linux/compiler.h>
+#include <linux/kmod.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/moduleparam.h>
diff --git a/sys/compat/linuxkpi/common/include/linux/sched.h b/sys/compat/linuxkpi/common/include/linux/sched.h
index 01d44a0ce1e7..589c0f1e50db 100644
--- a/sys/compat/linuxkpi/common/include/linux/sched.h
+++ b/sys/compat/linuxkpi/common/include/linux/sched.h
@@ -37,7 +37,6 @@
#include <sys/sched.h>
#include <sys/sleepqueue.h>
-#include <linux/list.h>
#include <linux/compat.h>
#include <linux/completion.h>
#include <linux/pid.h>
@@ -55,6 +54,7 @@
#define TASK_UNINTERRUPTIBLE 0x0002
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
#define TASK_WAKING 0x0100
+#define TASK_PARKED 0x0200
struct task_struct {
struct thread *task_thread;
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index 8df5de6329b6..a802ef999472 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -497,7 +497,7 @@ linux_cdev_pager_populate(vm_object_t vm_obj, vm_pindex_t pidx, int fault_type,
VM_OBJECT_WUNLOCK(vm_obj);
down_write(&vmap->vm_mm->mmap_sem);
- if (unlikely(vmap->vm_ops == NULL)) {
+ if (unlikely(vmap->vm_ops == NULL || vmap->vm_ops->fault == NULL)) {
err = VM_FAULT_SIGBUS;
} else {
vmap->vm_pfn_count = 0;
@@ -1173,8 +1173,7 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
if (vmap->vm_ops != NULL) {
void *vm_private_data;
- if (vmap->vm_ops->fault == NULL ||
- vmap->vm_ops->open == NULL ||
+ if (vmap->vm_ops->open == NULL ||
vmap->vm_ops->close == NULL ||
vmap->vm_private_data == NULL) {
linux_cdev_handle_free(vmap);
@@ -2027,6 +2026,8 @@ linux_compat_uninit(void *arg)
linux_kobject_kfree_name(&linux_root_device.kobj);
linux_kobject_kfree_name(&linux_class_misc.kobj);
+ mtx_destroy(&vmmaplock);
+ spin_lock_destroy(&pci_lock);
rw_destroy(&linux_vma_lock);
}
SYSUNINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_uninit, NULL);
diff --git a/sys/compat/linuxkpi/common/src/linux_current.c b/sys/compat/linuxkpi/common/src/linux_current.c
index f64c8c731947..f0d1e199e816 100644
--- a/sys/compat/linuxkpi/common/src/linux_current.c
+++ b/sys/compat/linuxkpi/common/src/linux_current.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include <linux/compat.h>
+#include <linux/completion.h>
#include <linux/mm.h>
#include <linux/kthread.h>
@@ -68,6 +69,8 @@ linux_alloc_current(struct thread *td, int flags)
ts->pid = td->td_tid;
atomic_set(&ts->usage, 1);
ts->state = TASK_RUNNING;
+ init_completion(&ts->parked);
+ init_completion(&ts->exited);
proc = td->td_proc;
diff --git a/sys/compat/linuxkpi/common/src/linux_hrtimer.c b/sys/compat/linuxkpi/common/src/linux_hrtimer.c
new file mode 100644
index 000000000000..42b2a9f978d3
--- /dev/null
+++ b/sys/compat/linuxkpi/common/src/linux_hrtimer.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/time.h>
+
+#include <machine/cpu.h>
+
+#include <linux/hrtimer.h>
+
+/* hrtimer flags */
+#define HRTIMER_ACTIVE 0x01
+
+static void
+hrtimer_call_handler(void *arg)
+{
+ struct hrtimer *hrtimer;
+ enum hrtimer_restart ret;
+
+ hrtimer = arg;
+ ret = hrtimer->function(hrtimer);
+ MPASS(ret == HRTIMER_NORESTART);
+ hrtimer->flags &= ~HRTIMER_ACTIVE;
+}
+
+bool
+linux_hrtimer_active(struct hrtimer *hrtimer)
+{
+ bool ret;
+
+ mtx_lock(&hrtimer->mtx);
+ ret = (hrtimer->flags & HRTIMER_ACTIVE) != 0;
+ mtx_unlock(&hrtimer->mtx);
+ return (ret);
+}
+
+int
+linux_hrtimer_cancel(struct hrtimer *hrtimer)
+{
+
+ if (!hrtimer_active(hrtimer))
+ return (0);
+ (void)callout_drain(&hrtimer->callout);
+ return (1);
+}
+
+void
+linux_hrtimer_init(struct hrtimer *hrtimer)
+{
+
+ hrtimer->function = NULL;
+ hrtimer->flags = 0;
+ mtx_init(&hrtimer->mtx, "hrtimer", NULL, MTX_DEF | MTX_RECURSE);
+ callout_init_mtx(&hrtimer->callout, &hrtimer->mtx, 0);
+}
+
+void
+linux_hrtimer_set_expires(struct hrtimer *hrtimer __unused,
+ ktime_t time __unused)
+{
+}
+
+void
+linux_hrtimer_start(struct hrtimer *hrtimer, ktime_t time)
+{
+
+ linux_hrtimer_start_range_ns(hrtimer, time, 0);
+}
+
+void
+linux_hrtimer_start_range_ns(struct hrtimer *hrtimer, ktime_t time, int64_t nsec)
+{
+
+ mtx_lock(&hrtimer->mtx);
+ callout_reset_sbt(&hrtimer->callout, time.tv64 * SBT_1NS,
+ nsec * SBT_1NS, hrtimer_call_handler, hrtimer, 0);
+ hrtimer->flags |= HRTIMER_ACTIVE;
+ mtx_unlock(&hrtimer->mtx);
+}
diff --git a/sys/compat/linuxkpi/common/src/linux_kthread.c b/sys/compat/linuxkpi/common/src/linux_kthread.c
index aa24e30d61f2..198082615076 100644
--- a/sys/compat/linuxkpi/common/src/linux_kthread.c
+++ b/sys/compat/linuxkpi/common/src/linux_kthread.c
@@ -43,21 +43,21 @@ enum {
};
bool
-kthread_should_stop_task(struct task_struct *task)
+linux_kthread_should_stop_task(struct task_struct *task)
{
return (atomic_read(&task->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
}
bool
-kthread_should_stop(void)
+linux_kthread_should_stop(void)
{
return (atomic_read(&current->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
}
int
-kthread_stop(struct task_struct *task)
+linux_kthread_stop(struct task_struct *task)
{
int retval;
@@ -66,6 +66,7 @@ kthread_stop(struct task_struct *task)
* kthread_stop():
*/
atomic_or(KTHREAD_SHOULD_STOP_MASK, &task->kthread_flags);
+ kthread_unpark(task);
wake_up_process(task);
wait_for_completion(&task->exited);
@@ -78,6 +79,53 @@ kthread_stop(struct task_struct *task)
return (retval);
}
+int
+linux_kthread_park(struct task_struct *task)
+{
+
+ atomic_or(KTHREAD_SHOULD_PARK_MASK, &task->kthread_flags);
+ wake_up_process(task);
+ wait_for_completion(&task->parked);
+ return (0);
+}
+
+void
+linux_kthread_parkme(void)
+{
+ struct task_struct *task;
+
+ task = current;
+ set_task_state(task, TASK_PARKED | TASK_UNINTERRUPTIBLE);
+ while (linux_kthread_should_park()) {
+ while ((atomic_fetch_or(KTHREAD_IS_PARKED_MASK,
+ &task->kthread_flags) & KTHREAD_IS_PARKED_MASK) == 0)
+ complete(&task->parked);
+ schedule();
+ set_task_state(task, TASK_PARKED | TASK_UNINTERRUPTIBLE);
+ }
+ atomic_andnot(KTHREAD_IS_PARKED_MASK, &task->kthread_flags);
+ set_task_state(task, TASK_RUNNING);
+}
+
+bool
+linux_kthread_should_park(void)
+{
+ struct task_struct *task;
+
+ task = current;
+ return (atomic_read(&task->kthread_flags) & KTHREAD_SHOULD_PARK_MASK);
+}
+
+void
+linux_kthread_unpark(struct task_struct *task)
+{
+
+ atomic_andnot(KTHREAD_SHOULD_PARK_MASK, &task->kthread_flags);
+ if ((atomic_fetch_andnot(KTHREAD_IS_PARKED_MASK, &task->kthread_flags) &
+ KTHREAD_IS_PARKED_MASK) != 0)
+ wake_up_state(task, TASK_PARKED);
+}
+
struct task_struct *
linux_kthread_setup_and_run(struct thread *td, linux_task_fn_t *task_fn, void *arg)
{
@@ -104,10 +152,10 @@ linux_kthread_fn(void *arg __unused)
{
struct task_struct *task = current;
- if (kthread_should_stop_task(task) == 0)
+ if (linux_kthread_should_stop_task(task) == 0)
task->task_ret = task->task_fn(task->task_data);
- if (kthread_should_stop_task(task) != 0) {
+ if (linux_kthread_should_stop_task(task) != 0) {
struct thread *td = curthread;
/* let kthread_stop() free data */
@@ -118,4 +166,3 @@ linux_kthread_fn(void *arg __unused)
}
kthread_exit();
}
-