Targeted for 12.0-release? Relnotes yes (linux64 support for NVidia driver)?
-- Send from a mobile device, please forgive brevity and misspellings. Am 06.11.2018 2:51 nachm. schrieb Tijl Coosemans <t...@freebsd.org>: > > Author: tijl > Date: Tue Nov 6 13:51:08 2018 > New Revision: 340181 > URL: https://svnweb.freebsd.org/changeset/base/340181 > > Log: > On amd64 both Linux compat modules, linux.ko and linux64.ko, provide > linux_ioctl_(un)register_handler that allows other driver modules to > register ioctl handlers. The ioctl syscall implementation in each Linux > compat module iterates over the list of handlers and forwards the call to > the appropriate driver. Because the registration functions have the same > name in each module it is not possible for a driver to support both 32 and > 64 bit linux compatibility. > > Move the list of ioctl handlers to linux_common.ko so it is shared by > both Linux modules and all drivers receive both 32 and 64 bit ioctl calls > with one registration. These ioctl handlers normally forward the call > to the FreeBSD ioctl handler which can handle both 32 and 64 bit. > > Keep the special COMPAT_LINUX32 ioctl handlers in linux.ko in a separate > list for now and let the ioctl syscall iterate over that list first. > Later, COMPAT_LINUX32 support can be added to the 64 bit ioctl handlers > via a runtime check for ILP32 like is done for COMPAT_FREEBSD32 and then > this separate list would disappear again. That is a much bigger effort > however and this commit is meant to be MFCable. > > This enables linux64 support in x11/nvidia-driver*. > > PR: 206711 http://www.FreeBSD.org/cgi/query-pr.cgi?pr=206711 > Reviewed by: kib > MFC after: 3 days > > Modified: > head/sys/amd64/linux32/linux32_sysvec.c > https://svnweb.FreeBSD.org/base/head/sys/amd64/linux32/linux32_sysvec > head/sys/compat/linux/linux_common.c > https://svnweb.FreeBSD.org/base/head/sys/compat/linux/linux_common > head/sys/compat/linux/linux_ioctl.c > https://svnweb.FreeBSD.org/base/head/sys/compat/linux/linux_ioctl > head/sys/compat/linux/linux_ioctl.h > https://svnweb.FreeBSD.org/base/head/sys/compat/linux/linux_ioctl > > Modified: head/sys/amd64/linux32/linux32_sysvec.c > ============================================================================== > > --- head/sys/amd64/linux32/linux32_sysvec.c Tue Nov 6 12:57:38 2018 > (r340180) > +++ head/sys/amd64/linux32/linux32_sysvec.c Tue Nov 6 13:51:08 2018 > (r340181) > @@ -1071,7 +1071,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 +1093,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"); > > Modified: head/sys/compat/linux/linux_common.c > ============================================================================== > > --- head/sys/compat/linux/linux_common.c Tue Nov 6 12:57:38 2018 (r340180) > +++ head/sys/compat/linux/linux_common.c Tue Nov 6 13:51:08 2018 (r340181) > @@ -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> > > @@ -47,6 +49,11 @@ FEATURE(linuxulator_v4l2, "V4L2 ioctl wrapper support > 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; > > Modified: head/sys/compat/linux/linux_ioctl.c > ============================================================================== > > --- head/sys/compat/linux/linux_ioctl.c Tue Nov 6 12:57:38 2018 (r340180) > +++ head/sys/compat/linux/linux_ioctl.c Tue Nov 6 13:51:08 2018 (r340181) > @@ -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,8 @@ linux_ioctl(struct thread *td, struct linux_ioctl_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) { > @@ -3716,6 +3719,18 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args > } > } > } > +#endif > + TAILQ_FOREACH(he, &linux_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); > + } > + } > + } > mtx_unlock(&Giant); > sx_sunlock(&linux_ioctl_sx); > fdrop(fp, td); > @@ -3737,7 +3752,7 @@ linux_ioctl(struct thread *td, struct linux_ioctl_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_handle > * 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_handle > 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_handle > 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,15 @@ linux_ioctl_register_handler(struct > linux_ioctl_handle > 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, &handlers, list) { > + TAILQ_FOREACH(he, &linux_ioctl_handlers, list) { > if (he->func == h->func) { > - TAILQ_REMOVE(&handlers, he, list); > + TAILQ_REMOVE(&linux_ioctl_handlers, he, list); > sx_xunlock(&linux_ioctl_sx); > free(he, M_LINUX); > return (0); > @@ -3798,3 +3813,69 @@ linux_ioctl_unregister_handler(struct linux_ioctl_hand > > 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, &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(&linux32_ioctl_handlers, he, list); > + sx_xunlock(&linux_ioctl_sx); > + free(he, M_LINUX); > + return (0); > + } > + } > + sx_xunlock(&linux_ioctl_sx); > + > + return (EINVAL); > +} > +#endif > > Modified: head/sys/compat/linux/linux_ioctl.h > ============================================================================== > > --- head/sys/compat/linux/linux_ioctl.h Tue Nov 6 12:57:38 2018 (r340180) > +++ head/sys/compat/linux/linux_ioctl.h Tue Nov 6 13:51:08 2018 (r340181) > @@ -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_ */ > _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"