diff options
Diffstat (limited to 'sys/compat')
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(¤t->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(); } - |
