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"

Reply via email to