€• ÅŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ./translations/zh_CN/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ./translations/zh_TW/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ./translations/it_IT/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ./translations/ja_JP/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ./translations/ko_KR/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ./translations/pt_BR/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ./translations/sp_SP/process/botching-up-ioctls”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ!(How to avoid) Botching up ioctls”h]”hŒ!(How to avoid) Botching up ioctls”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒH/var/lib/git/docbuild/linux/Documentation/process/botching-up-ioctls.rst”h´KubhŒ paragraph”“”)”}”(hŒ;From: https://blog.ffwll.ch/2013/11/botching-up-ioctls.html”h]”(hŒFrom: ”…””}”(hhÍh²hh³Nh´NubhŒ reference”“”)”}”(hŒ5https://blog.ffwll.ch/2013/11/botching-up-ioctls.html”h]”hŒ5https://blog.ffwll.ch/2013/11/botching-up-ioctls.html”…””}”(hh×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”hÙuh1hÕhhÍubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)”}”(hŒ6By: Daniel Vetter, Copyright © 2013 Intel Corporation”h]”hŒ6By: Daniel Vetter, Copyright © 2013 Intel Corporation”…””}”(hhìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)”}”(hX÷One clear insight kernel graphics hackers gained in the past few years is that trying to come up with a unified interface to manage the execution units and memory on completely different GPUs is a futile effort. So nowadays every driver has its own set of ioctls to allocate memory and submit work to the GPU. Which is nice, since there's no more insanity in the form of fake-generic, but actually only used once interfaces. But the clear downside is that there's much more potential to screw things up.”h]”hXûOne clear insight kernel graphics hackers gained in the past few years is that trying to come up with a unified interface to manage the execution units and memory on completely different GPUs is a futile effort. So nowadays every driver has its own set of ioctls to allocate memory and submit work to the GPU. Which is nice, since there’s no more insanity in the form of fake-generic, but actually only used once interfaces. But the clear downside is that there’s much more potential to screw things up.”…””}”(hhúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubhÌ)”}”(hXfTo avoid repeating all the same mistakes again I've written up some of the lessons learned while botching the job for the drm/i915 driver. Most of these only cover technicalities and not the big-picture issues like what the command submission ioctl exactly should look like. Learning these lessons is probably something every GPU driver has to do on its own.”h]”hXhTo avoid repeating all the same mistakes again I’ve written up some of the lessons learned while botching the job for the drm/i915 driver. Most of these only cover technicalities and not the big-picture issues like what the command submission ioctl exactly should look like. Learning these lessons is probably something every GPU driver has to do on its own.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubh¶)”}”(hhh]”(h»)”}”(hŒ Prerequisites”h]”hŒ Prerequisites”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjh²hh³hÊh´KubhÌ)”}”(hŒsFirst the prerequisites. Without these you have already failed, because you will need to add a 32-bit compat layer:”h]”hŒsFirst the prerequisites. Without these you have already failed, because you will need to add a 32-bit compat layer:”…””}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khjh²hubhŒ block_quote”“”)”}”(hXT* Only use fixed sized integers. To avoid conflicts with typedefs in userspace the kernel has special types like __u32, __s64. Use them. * Align everything to the natural size and use explicit padding. 32-bit platforms don't necessarily align 64-bit values to 64-bit boundaries, but 64-bit platforms do. So we always need padding to the natural size to get this right. * Pad the entire struct to a multiple of 64-bits if the structure contains 64-bit types - the structure size will otherwise differ on 32-bit versus 64-bit. Having a different structure size hurts when passing arrays of structures to the kernel, or if the kernel checks the structure size, which e.g. the drm core does. * Pointers are __u64, cast from/to a uintptr_t on the userspace side and from/to a void __user * in the kernel. Try really hard not to delay this conversion or worse, fiddle the raw __u64 through your code since that diminishes the checking tools like sparse can provide. The macro u64_to_user_ptr can be used in the kernel to avoid warnings about integers and pointers of different sizes. ”h]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ‡Only use fixed sized integers. To avoid conflicts with typedefs in userspace the kernel has special types like __u32, __s64. Use them. ”h]”hÌ)”}”(hŒ†Only use fixed sized integers. To avoid conflicts with typedefs in userspace the kernel has special types like __u32, __s64. Use them.”h]”hŒ†Only use fixed sized integers. To avoid conflicts with typedefs in userspace the kernel has special types like __u32, __s64. Use them.”…””}”(hjFh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhjBubah}”(h]”h ]”h"]”h$]”h&]”uh1j@hj=ubjA)”}”(hŒæAlign everything to the natural size and use explicit padding. 32-bit platforms don't necessarily align 64-bit values to 64-bit boundaries, but 64-bit platforms do. So we always need padding to the natural size to get this right. ”h]”hÌ)”}”(hŒåAlign everything to the natural size and use explicit padding. 32-bit platforms don't necessarily align 64-bit values to 64-bit boundaries, but 64-bit platforms do. So we always need padding to the natural size to get this right.”h]”hŒçAlign everything to the natural size and use explicit padding. 32-bit platforms don’t necessarily align 64-bit values to 64-bit boundaries, but 64-bit platforms do. So we always need padding to the natural size to get this right.”…””}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K!hjZubah}”(h]”h ]”h"]”h$]”h&]”uh1j@hj=ubjA)”}”(hX=Pad the entire struct to a multiple of 64-bits if the structure contains 64-bit types - the structure size will otherwise differ on 32-bit versus 64-bit. Having a different structure size hurts when passing arrays of structures to the kernel, or if the kernel checks the structure size, which e.g. the drm core does. ”h]”hÌ)”}”(hX<Pad the entire struct to a multiple of 64-bits if the structure contains 64-bit types - the structure size will otherwise differ on 32-bit versus 64-bit. Having a different structure size hurts when passing arrays of structures to the kernel, or if the kernel checks the structure size, which e.g. the drm core does.”h]”hX<Pad the entire struct to a multiple of 64-bits if the structure contains 64-bit types - the structure size will otherwise differ on 32-bit versus 64-bit. Having a different structure size hurts when passing arrays of structures to the kernel, or if the kernel checks the structure size, which e.g. the drm core does.”…””}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K&hjrubah}”(h]”h ]”h"]”h$]”h&]”uh1j@hj=ubjA)”}”(hX…Pointers are __u64, cast from/to a uintptr_t on the userspace side and from/to a void __user * in the kernel. Try really hard not to delay this conversion or worse, fiddle the raw __u64 through your code since that diminishes the checking tools like sparse can provide. The macro u64_to_user_ptr can be used in the kernel to avoid warnings about integers and pointers of different sizes. ”h]”hÌ)”}”(hXƒPointers are __u64, cast from/to a uintptr_t on the userspace side and from/to a void __user * in the kernel. Try really hard not to delay this conversion or worse, fiddle the raw __u64 through your code since that diminishes the checking tools like sparse can provide. The macro u64_to_user_ptr can be used in the kernel to avoid warnings about integers and pointers of different sizes.”h]”hXƒPointers are __u64, cast from/to a uintptr_t on the userspace side and from/to a void __user * in the kernel. Try really hard not to delay this conversion or worse, fiddle the raw __u64 through your code since that diminishes the checking tools like sparse can provide. The macro u64_to_user_ptr can be used in the kernel to avoid warnings about integers and pointers of different sizes.”…””}”(hjŽh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K,hjŠubah}”(h]”h ]”h"]”h$]”h&]”uh1j@hj=ubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1j;h³hÊh´Khj7ubah}”(h]”h ]”h"]”h$]”h&]”uh1j5h³hÊh´Khjh²hubeh}”(h]”Œ prerequisites”ah ]”h"]”Œ prerequisites”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒBasics”h]”hŒBasics”…””}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj¸h²hh³hÊh´K5ubhÌ)”}”(hX8With the joys of writing a compat layer avoided we can take a look at the basic fumbles. Neglecting these will make backward and forward compatibility a real pain. And since getting things wrong on the first attempt is guaranteed you will have a second iteration or at least an extension for any given interface.”h]”hX8With the joys of writing a compat layer avoided we can take a look at the basic fumbles. Neglecting these will make backward and forward compatibility a real pain. And since getting things wrong on the first attempt is guaranteed you will have a second iteration or at least an extension for any given interface.”…””}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K7hj¸h²hubj6)”}”(hXE* Have a clear way for userspace to figure out whether your new ioctl or ioctl extension is supported on a given kernel. If you can't rely on old kernels rejecting the new flags/modes or ioctls (since doing that was botched in the past) then you need a driver feature flag or revision number somewhere. * Have a plan for extending ioctls with new flags or new fields at the end of the structure. The drm core checks the passed-in size for each ioctl call and zero-extends any mismatches between kernel and userspace. That helps, but isn't a complete solution since newer userspace on older kernels won't notice that the newly added fields at the end get ignored. So this still needs a new driver feature flags. * Check all unused fields and flags and all the padding for whether it's 0, and reject the ioctl if that's not the case. Otherwise your nice plan for future extensions is going right down the gutters since someone will submit an ioctl struct with random stack garbage in the yet unused parts. Which then bakes in the ABI that those fields can never be used for anything else but garbage. This is also the reason why you must explicitly pad all structures, even if you never use them in an array - the padding the compiler might insert could contain garbage. * Have simple testcases for all of the above. ”h]”j<)”}”(hhh]”(jA)”}”(hX-Have a clear way for userspace to figure out whether your new ioctl or ioctl extension is supported on a given kernel. If you can't rely on old kernels rejecting the new flags/modes or ioctls (since doing that was botched in the past) then you need a driver feature flag or revision number somewhere. ”h]”hÌ)”}”(hX,Have a clear way for userspace to figure out whether your new ioctl or ioctl extension is supported on a given kernel. If you can't rely on old kernels rejecting the new flags/modes or ioctls (since doing that was botched in the past) then you need a driver feature flag or revision number somewhere.”h]”hX.Have a clear way for userspace to figure out whether your new ioctl or ioctl extension is supported on a given kernel. If you can’t rely on old kernels rejecting the new flags/modes or ioctls (since doing that was botched in the past) then you need a driver feature flag or revision number somewhere.”…””}”(hjâh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K