€•6EŒ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Œ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”…””}”(hhøhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hhõ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 KhhõhžhubhÊ)”}”(hŒThe GPU offers 3 levels:”h]”hŒThe GPU offers 3 levels:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K%hhõ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”…””}”(hj/hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸ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.”…””}”(hjBhž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&]”uh1j'hŸh³h K+hj$ubj()”}”(hŒtLevel 1 Preemption occurs at either bin level, if using GMEM rendering, or draw level in the sysmem rendering case. ”h]”(j.)”}”(hŒLevel 1”h]”hŒLevel 1”…””}”(hj`hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h K/hj\ubj>)”}”(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.”…””}”(hjqhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K.hjnubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj\ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h K/hj$hžhubj()”}”(hŒ)Level 2 Preemption occurs at draw level. ”h]”(j.)”}”(hŒLevel 2”h]”hŒLevel 2”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h K2hj‹ubj>)”}”(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 K2hjubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj‹ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h K2hj$hžhubeh}”(h]”h ]”h"]”h$]”h&]”uh1j"hhõ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 K4hhõ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 K6hhõ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”…””}”(hjûhž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.”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KAhjøhžhubj#)”}”(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]”(j.)”}”(hŒ SMMU_INFO”h]”hŒ SMMU_INFO”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h KLhjubj>)”}”(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.”…””}”(hj/hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KHhj,ubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h KLhjubj()”}”(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]”(j.)”}”(hŒ NON_SECURE”h]”hŒ NON_SECURE”…””}”(hjMhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h KQhjIubj>)”}”(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.”…””}”(hj^hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KOhj[ubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjIubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h KQhjhžhubj()”}”(hŒ:SECURE This saves state related to the GPU's secure mode. ”h]”(j.)”}”(hŒSECURE”h]”hŒSECURE”…””}”(hj|hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h KThjxubj>)”}”(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.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KThjŠubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjxubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h KThjhž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]”(j.)”}”(hŒNON_PRIV”h]”hŒNON_PRIV”…””}”(hj«hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h KXhj§ubj>)”}”(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&]”uh1j=hj§ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h KXhjhžhubj()”}”(hŒFCOUNTER This record is used to save and restore performance counters. ”h]”(j.)”}”(hŒCOUNTER”h]”hŒCOUNTER”…””}”(hjÚhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hŸh³h K[hjÖubj>)”}”(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&]”uh1j=hjÖubeh}”(h]”h ]”h"]”h$]”h&]”uh1j'hŸh³h K[hjhžhubeh}”(h]”h ]”h"]”h$]”h&]”uh1j"hjø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.”…””}”(hj hž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”jLŒ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&j#jõjòjjuŒ nametypes”}”(j&‰jõ‰j‰uh}”(j#h¶jòhõjjø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.