€• FŒ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/gpu/msm-preemption”Œ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/gpu/msm-preemption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/it_IT/gpu/msm-preemption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ja_JP/gpu/msm-preemption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ko_KR/gpu/msm-preemption”Œ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/gpu/msm-preemption”Œ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/gpu/msm-preemption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³Œ@/var/lib/git/docbuild/linux/Documentation/gpu/msm-preemption.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒMSM Preemption”h]”hŒMSM Preemption”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒŒPreemption allows Adreno GPUs to switch to a higher priority ring when work is pushed to it, reducing latency for high priority submissions.”h]”hŒŒPreemption allows Adreno GPUs to switch to a higher priority ring when work is pushed to it, reducing latency for high priority submissions.”…””}”(hhßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hhÊh²hubhÞ)”}”(hX`When preemption is enabled 4 rings are initialized, corresponding to different priority levels. Having multiple rings is purely a software concept as the GPU only has registers to keep track of one graphics ring. The kernel is able to switch which ring is currently being processed by requesting preemption. When certain conditions are met, depending on the priority level, the GPU will save its current state in a series of buffers, then restores state from a similar set of buffers specified by the kernel. It then resumes execution and fires an IRQ to let the kernel know the context switch has completed.”h]”hX`When preemption is enabled 4 rings are initialized, corresponding to different priority levels. Having multiple rings is purely a software concept as the GPU only has registers to keep track of one graphics ring. The kernel is able to switch which ring is currently being processed by requesting preemption. When certain conditions are met, depending on the priority level, the GPU will save its current state in a series of buffers, then restores state from a similar set of buffers specified by the kernel. It then resumes execution and fires an IRQ to let the kernel know the context switch has completed.”…””}”(hhíh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hhÊh²hubhÞ)”}”(hXsThis mechanism can be used by the kernel to switch between rings. Whenever a submission occurs the kernel finds the highest priority ring which isn't empty and preempts to it if said ring is not the one being currently executed. This is also done whenever a submission completes to make sure execution resumes on a lower priority ring when a higher priority ring is done.”h]”hXuThis mechanism can be used by the kernel to switch between rings. Whenever a submission occurs the kernel finds the highest priority ring which isn’t empty and preempts to it if said ring is not the one being currently executed. This is also done whenever a submission completes to make sure execution resumes on a lower priority ring when a higher priority ring is done.”…””}”(hhûh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhhÊh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒPreemption levels”h]”hŒPreemption levels”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj h²hh³hÇh´KubhÞ)”}”(hXJPreemption can only occur at certain boundaries. The exact conditions can be configured by changing the preemption level, this allows to compromise between latency (ie. the time that passes between when the kernel requests preemption and when the SQE begins saving state) and overhead (the amount of state that needs to be saved).”h]”hXJPreemption can only occur at certain boundaries. The exact conditions can be configured by changing the preemption level, this allows to compromise between latency (ie. the time that passes between when the kernel requests preemption and when the SQE begins saving state) and overhead (the amount of state that needs to be saved).”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj h²hubhÞ)”}”(hŒThe GPU offers 3 levels:”h]”hŒThe GPU offers 3 levels:”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K%hj h²hubhŒdefinition_list”“”)”}”(hhh]”(hŒdefinition_list_item”“”)”}”(hXLevel 0 Preemption only occurs at the submission level. This requires the least amount of state to be saved as the execution of userspace submitted IBs is never interrupted, however it offers very little benefit compared to not enabling preemption of any kind. ”h]”(hŒterm”“”)”}”(hŒLevel 0”h]”hŒLevel 0”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´K+hj=ubhŒ definition”“”)”}”(hhh]”hÞ)”}”(hŒüPreemption only occurs at the submission level. This requires the least amount of state to be saved as the execution of userspace submitted IBs is never interrupted, however it offers very little benefit compared to not enabling preemption of any kind.”h]”hŒüPreemption only occurs at the submission level. This requires the least amount of state to be saved as the execution of userspace submitted IBs is never interrupted, however it offers very little benefit compared to not enabling preemption of any kind.”…””}”(hjVh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K(hjSubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhj=ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´K+hj8ubj<)”}”(hŒtLevel 1 Preemption occurs at either bin level, if using GMEM rendering, or draw level in the sysmem rendering case. ”h]”(jB)”}”(hŒLevel 1”h]”hŒLevel 1”…””}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´K/hjpubjR)”}”(hhh]”hÞ)”}”(hŒkPreemption occurs at either bin level, if using GMEM rendering, or draw level in the sysmem rendering case.”h]”hŒkPreemption occurs at either bin level, if using GMEM rendering, or draw level in the sysmem rendering case.”…””}”(hj…h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K.hj‚ubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhjpubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´K/hj8h²hubj<)”}”(hŒ)Level 2 Preemption occurs at draw level. ”h]”(jB)”}”(hŒLevel 2”h]”hŒLevel 2”…””}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´K2hjŸubjR)”}”(hhh]”hÞ)”}”(hŒ Preemption occurs at draw level.”h]”hŒ Preemption occurs at draw level.”…””}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K2hj±ubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhjŸubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´K2hj8h²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1j6hj h²hh³hÇh´NubhÞ)”}”(hŒ3Level 1 is the mode that is used by the msm driver.”h]”hŒ3Level 1 is the mode that is used by the msm driver.”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K4hj h²hubhÞ)”}”(hXóAdditionally the GPU allows to specify a `skip_save_restore` option. This disables the saving and restoring of all registers except those relating to the operation of the SQE itself, reducing overhead. Saving and restoring is only skipped when using GMEM with Level 1 preemption. When enabling this userspace is expected to set the state that isn't preserved whenever preemption occurs which is done by specifying preamble and postambles. Those are IBs that are executed before and after preemption.”h]”(hŒ)Additionally the GPU allows to specify a ”…””}”(hjâh²hh³Nh´NubhŒtitle_reference”“”)”}”(hŒ`skip_save_restore`”h]”hŒskip_save_restore”…””}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jêhjâubhX¹ option. This disables the saving and restoring of all registers except those relating to the operation of the SQE itself, reducing overhead. Saving and restoring is only skipped when using GMEM with Level 1 preemption. When enabling this userspace is expected to set the state that isn’t preserved whenever preemption occurs which is done by specifying preamble and postambles. Those are IBs that are executed before and after preemption.”…””}”(hjâh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K6hj h²hubeh}”(h]”Œpreemption-levels”ah ]”h"]”Œpreemption levels”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒPreemption buffers”h]”hŒPreemption buffers”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj h²hh³hÇh´K?ubhÞ)”}”(hX„A series of buffers are necessary to store the state of rings while they are not being executed. There are different kinds of preemption records and most of those require one buffer per ring. This is because preemption never occurs between submissions on the same ring, which always run in sequence when the ring is active. This means that only one context per ring is effectively active.”h]”hX„A series of buffers are necessary to store the state of rings while they are not being executed. There are different kinds of preemption records and most of those require one buffer per ring. This is because preemption never occurs between submissions on the same ring, which always run in sequence when the ring is active. This means that only one context per ring is effectively active.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KAhj h²hubj7)”}”(hhh]”(j<)”}”(hX9SMMU_INFO This buffer contains info about the current SMMU configuration such as the ttbr0 register. The SQE firmware isn't actually able to save this record. As a result SMMU info must be saved manually from the CP to a buffer and the SMMU record updated with info from said buffer before triggering preemption. ”h]”(jB)”}”(hŒ SMMU_INFO”h]”hŒ SMMU_INFO”…””}”(hj2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´KLhj.ubjR)”}”(hhh]”hÞ)”}”(hX.This buffer contains info about the current SMMU configuration such as the ttbr0 register. The SQE firmware isn't actually able to save this record. As a result SMMU info must be saved manually from the CP to a buffer and the SMMU record updated with info from said buffer before triggering preemption.”h]”hX0This buffer contains info about the current SMMU configuration such as the ttbr0 register. The SQE firmware isn’t actually able to save this record. As a result SMMU info must be saved manually from the CP to a buffer and the SMMU record updated with info from said buffer before triggering preemption.”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KHhj@ubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhj.ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´KLhj+ubj<)”}”(hŒ²NON_SECURE This is the main preemption record where most state is saved. It is mostly opaque to the kernel except for the first few words that must be initialized by the kernel. ”h]”(jB)”}”(hŒ NON_SECURE”h]”hŒ NON_SECURE”…””}”(hjah²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´KQhj]ubjR)”}”(hhh]”hÞ)”}”(hŒ¦This is the main preemption record where most state is saved. It is mostly opaque to the kernel except for the first few words that must be initialized by the kernel.”h]”hŒ¦This is the main preemption record where most state is saved. It is mostly opaque to the kernel except for the first few words that must be initialized by the kernel.”…””}”(hjrh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KOhjoubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhj]ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´KQhj+h²hubj<)”}”(hŒ:SECURE This saves state related to the GPU's secure mode. ”h]”(jB)”}”(hŒSECURE”h]”hŒSECURE”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´KThjŒubjR)”}”(hhh]”hÞ)”}”(hŒ2This saves state related to the GPU's secure mode.”h]”hŒ4This saves state related to the GPU’s secure mode.”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KThjžubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhjŒubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´KThj+h²hubj<)”}”(hŒƒNON_PRIV The intended purpose of this record is unknown. The SQE firmware actually ignores it and therefore msm doesn't handle it. ”h]”(jB)”}”(hŒNON_PRIV”h]”hŒNON_PRIV”…””}”(hj¿h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´KXhj»ubjR)”}”(hhh]”hÞ)”}”(hŒyThe intended purpose of this record is unknown. The SQE firmware actually ignores it and therefore msm doesn't handle it.”h]”hŒ{The intended purpose of this record is unknown. The SQE firmware actually ignores it and therefore msm doesn’t handle it.”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KWhjÍubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhj»ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´KXhj+h²hubj<)”}”(hŒFCOUNTER This record is used to save and restore performance counters. ”h]”(jB)”}”(hŒCOUNTER”h]”hŒCOUNTER”…””}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAh³hÇh´K[hjêubjR)”}”(hhh]”hÞ)”}”(hŒ=This record is used to save and restore performance counters.”h]”hŒ=This record is used to save and restore performance counters.”…””}”(hjÿh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K[hjüubah}”(h]”h ]”h"]”h$]”h&]”uh1jQhjêubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;h³hÇh´K[hj+h²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1j6hj h²hh³hÇh´NubhÞ)”}”(hXÌHandling the permissions of those buffers is critical for security. All but the NON_PRIV records need to be inaccessible from userspace, so they must be mapped in the kernel address space with the MSM_BO_MAP_PRIV flag. For example, making the NON_SECURE record accessible from userspace would allow any process to manipulate a saved ring's RPTR which can be used to skip the execution of some packets in a ring and execute user commands with higher privileges.”h]”hXÎHandling the permissions of those buffers is critical for security. All but the NON_PRIV records need to be inaccessible from userspace, so they must be mapped in the kernel address space with the MSM_BO_MAP_PRIV flag. For example, making the NON_SECURE record accessible from userspace would allow any process to manipulate a saved ring’s RPTR which can be used to skip the execution of some packets in a ring and execute user commands with higher privileges.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K]hj h²hubeh}”(h]”Œpreemption-buffers”ah ]”h"]”Œpreemption buffers”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K?ubeh}”(h]”Œmsm-preemption”ah ]”h"]”Œmsm preemption”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j`Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j:j7j jj2j/uŒ nametypes”}”(j:‰j ‰j2‰uh}”(j7hÊjj j/j uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.