€•‹ÃŒ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/mm/page_tables”Œ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/mm/page_tables”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/it_IT/mm/page_tables”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/ja_JP/mm/page_tables”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/ko_KR/mm/page_tables”Œ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/mm/page_tables”Œ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/mm/page_tables”Œ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³Œ| P4D | +-----+ | | +-----+ +-->| PUD | +-----+ | | +-----+ +-->| PMD | +-----+ | | +-----+ +-->| PTE | +-----+”h]”hX‡+-----+ | PGD | +-----+ | | +-----+ +-->| P4D | +-----+ | | +-----+ +-->| PUD | +-----+ | | +-----+ +-->| PMD | +-----+ | | +-----+ +-->| PTE | +-----+”…”�”}”hj-sbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1j+h³hÇh´K?hhÊh²hubhÞ)�”}”(hŒqSymbols on the different levels of the page table hierarchy have the following meaning beginning from the bottom:”h]”hŒqSymbols on the different levels of the page table hierarchy have the following meaning beginning from the bottom:”…”�”}”(hj;h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KThhÊh²hubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hX>**pte**, `pte_t`, `pteval_t` = **Page Table Entry** - mentioned earlier. The *pte* is an array of `PTRS_PER_PTE` elements of the `pteval_t` type, each mapping a single page of virtual memory to a single page of physical memory. The architecture defines the size and contents of `pteval_t`. A typical example is that the `pteval_t` is a 32- or 64-bit value with the upper bits being a **pfn** (page frame number), and the lower bits being some architecture-specific bits such as memory protection. The **entry** part of the name is a bit confusing because while in Linux 1.0 this did refer to a single page table entry in the single top level page table, it was retrofitted to be an array of mapping elements when two-level page tables were first introduced, so the *pte* is the lowermost page *table*, not a page table *entry*. ”h]”(hÞ)�”}”(hX!**pte**, `pte_t`, `pteval_t` = **Page Table Entry** - mentioned earlier. The *pte* is an array of `PTRS_PER_PTE` elements of the `pteval_t` type, each mapping a single page of virtual memory to a single page of physical memory. The architecture defines the size and contents of `pteval_t`.”h]”(j)�”}”(hŒ**pte**”h]”hŒpte”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjTubhŒ, ”…”�”}”(hjTh²hh³Nh´Nubj8)�”}”(hŒ`pte_t`”h]”hŒpte_t”…”�”}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjTubhŒ, ”…”�”}”hjTsbj8)�”}”(hŒ `pteval_t`”h]”hŒpteval_t”…”�”}”(hj|h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjTubhŒ = ”…”�”}”(hjTh²hh³Nh´Nubj)�”}”(hŒ**Page Table Entry**”h]”hŒPage Table Entry”…”�”}”(hjŽh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjTubhŒ - mentioned earlier. The ”…”�”}”(hjTh²hh³Nh´NubjZ)�”}”(hŒ*pte*”h]”hŒpte”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhjTubhŒ is an array of ”…”�”}”(hjTh²hh³Nh´Nubj8)�”}”(hŒ`PTRS_PER_PTE`”h]”hŒ PTRS_PER_PTE”…”�”}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjTubhŒ elements of the ”…”�”}”(hjTh²hh³Nh´Nubj8)�”}”(hŒ `pteval_t`”h]”hŒpteval_t”…”�”}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjTubhŒ‹ type, each mapping a single page of virtual memory to a single page of physical memory. The architecture defines the size and contents of ”…”�”}”(hjTh²hh³Nh´Nubj8)�”}”(hŒ `pteval_t`”h]”hŒpteval_t”…”�”}”(hjÖh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjTubhŒ.”…”�”}”(hjTh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KWhjPubhÞ)�”}”(hŒÎA typical example is that the `pteval_t` is a 32- or 64-bit value with the upper bits being a **pfn** (page frame number), and the lower bits being some architecture-specific bits such as memory protection.”h]”(hŒA typical example is that the ”…”�”}”(hjîh²hh³Nh´Nubj8)�”}”(hŒ `pteval_t`”h]”hŒpteval_t”…”�”}”(hjöh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjîubhŒ6 is a 32- or 64-bit value with the upper bits being a ”…”�”}”(hjîh²hh³Nh´Nubj)�”}”(hŒ**pfn**”h]”hŒpfn”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjîubhŒi (page frame number), and the lower bits being some architecture-specific bits such as memory protection.”…”�”}”(hjîh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K\hjPubhÞ)�”}”(hXJThe **entry** part of the name is a bit confusing because while in Linux 1.0 this did refer to a single page table entry in the single top level page table, it was retrofitted to be an array of mapping elements when two-level page tables were first introduced, so the *pte* is the lowermost page *table*, not a page table *entry*.”h]”(hŒThe ”…”�”}”(hj h²hh³Nh´Nubj)�”}”(hŒ **entry**”h]”hŒentry”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj ubhŒÿ part of the name is a bit confusing because while in Linux 1.0 this did refer to a single page table entry in the single top level page table, it was retrofitted to be an array of mapping elements when two-level page tables were first introduced, so the ”…”�”}”(hj h²hh³Nh´NubjZ)�”}”(hŒ*pte*”h]”hŒpte”…”�”}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj ubhŒ is the lowermost page ”…”�”}”(hj h²hh³Nh´NubjZ)�”}”(hŒ*table*”h]”hŒtable”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj ubhŒ, not a page table ”…”�”}”(hj h²hh³Nh´NubjZ)�”}”(hŒ*entry*”h]”hŒentry”…”�”}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj ubhŒ.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K`hjPubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhjKh²hh³hÇh´NubjO)�”}”(hŒŽ**pmd**, `pmd_t`, `pmdval_t` = **Page Middle Directory**, the hierarchy right above the *pte*, with `PTRS_PER_PMD` references to the *pte*:s. ”h]”hÞ)�”}”(hŒ�**pmd**, `pmd_t`, `pmdval_t` = **Page Middle Directory**, the hierarchy right above the *pte*, with `PTRS_PER_PMD` references to the *pte*:s.”h]”(j)�”}”(hŒ**pmd**”h]”hŒpmd”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj€ubhŒ, ”…”�”}”(hj€h²hh³Nh´Nubj8)�”}”(hŒ`pmd_t`”h]”hŒpmd_t”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj€ubhŒ, ”…”�”}”hj€sbj8)�”}”(hŒ `pmdval_t`”h]”hŒpmdval_t”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj€ubhŒ = ”…”�”}”(hj€h²hh³Nh´Nubj)�”}”(hŒ**Page Middle Directory**”h]”hŒPage Middle Directory”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj€ubhŒ , the hierarchy right above the ”…”�”}”(hj€h²hh³Nh´NubjZ)�”}”(hŒ*pte*”h]”hŒpte”…”�”}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj€ubhŒ, with ”…”�”}”(hj€h²hh³Nh´Nubj8)�”}”(hŒ`PTRS_PER_PMD`”h]”hŒ PTRS_PER_PMD”…”�”}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj€ubhŒ references to the ”…”�”}”(hj€h²hh³Nh´NubjZ)�”}”(hŒ*pte*”h]”hŒpte”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj€ubhŒ:s.”…”�”}”(hj€h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kfhj|ubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjKh²hh³hÇh´NubjO)�”}”(hŒ½**pud**, `pud_t`, `pudval_t` = **Page Upper Directory** was introduced after the other levels to handle 4-level page tables. It is potentially unused, or *folded* as we will discuss later. ”h]”hÞ)�”}”(hŒ¼**pud**, `pud_t`, `pudval_t` = **Page Upper Directory** was introduced after the other levels to handle 4-level page tables. It is potentially unused, or *folded* as we will discuss later.”h]”(j)�”}”(hŒ**pud**”h]”hŒpud”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubhŒ, ”…”�”}”(hjh²hh³Nh´Nubj8)�”}”(hŒ`pud_t`”h]”hŒpud_t”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjubhŒ, ”…”�”}”hjsbj8)�”}”(hŒ `pudval_t`”h]”hŒpudval_t”…”�”}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjubhŒ = ”…”�”}”(hjh²hh³Nh´Nubj)�”}”(hŒ**Page Upper Directory**”h]”hŒPage Upper Directory”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubhŒc was introduced after the other levels to handle 4-level page tables. It is potentially unused, or ”…”�”}”(hjh²hh³Nh´NubjZ)�”}”(hŒ*folded*”h]”hŒfolded”…”�”}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhjubhŒ as we will discuss later.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kihjubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjKh²hh³hÇh´NubjO)�”}”(hXŽ**p4d**, `p4d_t`, `p4dval_t` = **Page Level 4 Directory** was introduced to handle 5-level page tables after the *pud* was introduced. Now it was clear that we needed to replace *pgd*, *pmd*, *pud* etc with a figure indicating the directory level and that we cannot go on with ad hoc names any more. This is only used on systems which actually have 5 levels of page tables, otherwise it is folded. ”h]”hÞ)�”}”(hX�**p4d**, `p4d_t`, `p4dval_t` = **Page Level 4 Directory** was introduced to handle 5-level page tables after the *pud* was introduced. Now it was clear that we needed to replace *pgd*, *pmd*, *pud* etc with a figure indicating the directory level and that we cannot go on with ad hoc names any more. This is only used on systems which actually have 5 levels of page tables, otherwise it is folded.”h]”(j)�”}”(hŒ**p4d**”h]”hŒp4d”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj€ubhŒ, ”…”�”}”(hj€h²hh³Nh´Nubj8)�”}”(hŒ`p4d_t`”h]”hŒp4d_t”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj€ubhŒ, ”…”�”}”hj€sbj8)�”}”(hŒ `p4dval_t`”h]”hŒp4dval_t”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj€ubhŒ = ”…”�”}”(hj€h²hh³Nh´Nubj)�”}”(hŒ**Page Level 4 Directory**”h]”hŒPage Level 4 Directory”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj€ubhŒ8 was introduced to handle 5-level page tables after the ”…”�”}”(hj€h²hh³Nh´NubjZ)�”}”(hŒ*pud*”h]”hŒpud”…”�”}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj€ubhŒ< was introduced. Now it was clear that we needed to replace ”…”�”}”(hj€h²hh³Nh´NubjZ)�”}”(hŒ*pgd*”h]”hŒpgd”…”�”}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj€ubhŒ, ”…”�”}”hj€sbjZ)�”}”(hŒ*pmd*”h]”hŒpmd”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj€ubhŒ, ”…”�”}”hj€sbjZ)�”}”(hŒ*pud*”h]”hŒpud”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj€ubhŒÈ etc with a figure indicating the directory level and that we cannot go on with ad hoc names any more. This is only used on systems which actually have 5 levels of page tables, otherwise it is folded.”…”�”}”(hj€h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kmhj|ubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjKh²hh³hÇh´NubjO)�”}”(hX**pgd**, `pgd_t`, `pgdval_t` = **Page Global Directory** - the Linux kernel main page table handling the PGD for the kernel memory is still found in `swapper_pg_dir`, but each userspace process in the system also has its own memory context and thus its own *pgd*, found in `struct mm_struct` which in turn is referenced to in each `struct task_struct`. So tasks have memory context in the form of a `struct mm_struct` and this in turn has a `struct pgt_t *pgd` pointer to the corresponding page global directory. ”h]”hÞ)�”}”(hX**pgd**, `pgd_t`, `pgdval_t` = **Page Global Directory** - the Linux kernel main page table handling the PGD for the kernel memory is still found in `swapper_pg_dir`, but each userspace process in the system also has its own memory context and thus its own *pgd*, found in `struct mm_struct` which in turn is referenced to in each `struct task_struct`. So tasks have memory context in the form of a `struct mm_struct` and this in turn has a `struct pgt_t *pgd` pointer to the corresponding page global directory.”h]”(j)�”}”(hŒ**pgd**”h]”hŒpgd”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj$ubhŒ, ”…”�”}”(hj$h²hh³Nh´Nubj8)�”}”(hŒ`pgd_t`”h]”hŒpgd_t”…”�”}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ, ”…”�”}”hj$sbj8)�”}”(hŒ `pgdval_t`”h]”hŒpgdval_t”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ = ”…”�”}”(hj$h²hh³Nh´Nubj)�”}”(hŒ**Page Global Directory**”h]”hŒPage Global Directory”…”�”}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj$ubhŒ] - the Linux kernel main page table handling the PGD for the kernel memory is still found in ”…”�”}”(hj$h²hh³Nh´Nubj8)�”}”(hŒ`swapper_pg_dir`”h]”hŒswapper_pg_dir”…”�”}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ\, but each userspace process in the system also has its own memory context and thus its own ”…”�”}”(hj$h²hh³Nh´NubjZ)�”}”(hŒ*pgd*”h]”hŒpgd”…”�”}”(hj‚h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj$ubhŒ , found in ”…”�”}”(hj$h²hh³Nh´Nubj8)�”}”(hŒ`struct mm_struct`”h]”hŒstruct mm_struct”…”�”}”(hj”h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ( which in turn is referenced to in each ”…”�”}”(hj$h²hh³Nh´Nubj8)�”}”(hŒ`struct task_struct`”h]”hŒstruct task_struct”…”�”}”(hj¦h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ0. So tasks have memory context in the form of a ”…”�”}”(hj$h²hh³Nh´Nubj8)�”}”(hŒ`struct mm_struct`”h]”hŒstruct mm_struct”…”�”}”(hj¸h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ and this in turn has a ”…”�”}”(hj$h²hh³Nh´Nubj8)�”}”(hŒ`struct pgt_t *pgd`”h]”hŒstruct pgt_t *pgd”…”�”}”(hjÊh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj$ubhŒ4 pointer to the corresponding page global directory.”…”�”}”(hj$h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kthj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjKh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jIh³hÇh´KWhhÊh²hubhÞ)�”}”(hXTo repeat: each level in the page table hierarchy is a *array of pointers*, so the **pgd** contains `PTRS_PER_PGD` pointers to the next level below, **p4d** contains `PTRS_PER_P4D` pointers to **pud** items and so on. The number of pointers on each level is architecture-defined.::”h]”(hŒ7To repeat: each level in the page table hierarchy is a ”…”�”}”(hjðh²hh³Nh´NubjZ)�”}”(hŒ*array of pointers*”h]”hŒarray of pointers”…”�”}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhjðubhŒ , so the ”…”�”}”(hjðh²hh³Nh´Nubj)�”}”(hŒ**pgd**”h]”hŒpgd”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjðubhŒ contains ”…”�”}”(hjðh²hh³Nh´Nubj8)�”}”(hŒ`PTRS_PER_PGD`”h]”hŒ PTRS_PER_PGD”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjðubhŒ# pointers to the next level below, ”…”�”}”(hjðh²hh³Nh´Nubj)�”}”(hŒ**p4d**”h]”hŒp4d”…”�”}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjðubhŒ contains ”…”�”}”(hjðh²hh³Nh´Nubj8)�”}”(hŒ`PTRS_PER_P4D`”h]”hŒ PTRS_PER_P4D”…”�”}”(hj@h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjðubhŒ pointers to ”…”�”}”(hjðh²hh³Nh´Nubj)�”}”(hŒ**pud**”h]”hŒpud”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjðubhŒP items and so on. The number of pointers on each level is architecture-defined.:”…”�”}”(hjðh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K|hhÊh²hubj,)�”}”(hXR PMD --> +-----+ PTE | ptr |-------> +-----+ | ptr |- | ptr |-------> PAGE | ptr | \ | ptr | | ptr | \ ... | ... | \ | ptr | \ PTE +-----+ +----> +-----+ | ptr |-------> PAGE | ptr | ...”h]”hXR PMD --> +-----+ PTE | ptr |-------> +-----+ | ptr |- | ptr |-------> PAGE | ptr | \ | ptr | | ptr | \ ... | ... | \ | ptr | \ PTE +-----+ +----> +-----+ | ptr |-------> PAGE | ptr | ...”…”�”}”hjjsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1j+h³hÇh´K�hhÊh²hubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒPage Table Folding”h]”hŒPage Table Folding”…”�”}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjxh²hh³hÇh´K�ubhÞ)�”}”(hŒêIf the architecture does not use all the page table levels, they can be *folded* which means skipped, and all operations performed on page tables will be compile-time augmented to just skip a level when accessing the next lower level.”h]”(hŒHIf the architecture does not use all the page table levels, they can be ”…”�”}”(hj‰h²hh³Nh´NubjZ)�”}”(hŒ*folded*”h]”hŒfolded”…”�”}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jYhj‰ubhŒš which means skipped, and all operations performed on page tables will be compile-time augmented to just skip a level when accessing the next lower level.”…”�”}”(hj‰h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K’hjxh²hubhÞ)�”}”(hXPage table handling code that wishes to be architecture-neutral, such as the virtual memory manager, will need to be written so that it traverses all of the currently five levels. This style should also be preferred for architecture-specific code, so as to be robust to future changes.”h]”hXPage table handling code that wishes to be architecture-neutral, such as the virtual memory manager, will need to be written so that it traverses all of the currently five levels. This style should also be preferred for architecture-specific code, so as to be robust to future changes.”…”�”}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K—hjxh²hubeh}”(h]”Œpage-table-folding”ah ]”h"]”Œpage table folding”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K�ubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒMMU, TLB, and Page Faults”h]”hŒMMU, TLB, and Page Faults”…”�”}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¿h²hh³hÇh´KžubhÞ)�”}”(hXThe `Memory Management Unit (MMU)` is a hardware component that handles virtual to physical address translations. It may use relatively small caches in hardware called `Translation Lookaside Buffers (TLBs)` and `Page Walk Caches` to speed up these translations.”h]”(hŒThe ”…”�”}”(hjÐh²hh³Nh´Nubj8)�”}”(hŒ`Memory Management Unit (MMU)`”h]”hŒMemory Management Unit (MMU)”…”�”}”(hjØh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÐubhŒ† is a hardware component that handles virtual to physical address translations. It may use relatively small caches in hardware called ”…”�”}”(hjÐh²hh³Nh´Nubj8)�”}”(hŒ&`Translation Lookaside Buffers (TLBs)`”h]”hŒ$Translation Lookaside Buffers (TLBs)”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÐubhŒ and ”…”�”}”(hjÐh²hh³Nh´Nubj8)�”}”(hŒ`Page Walk Caches`”h]”hŒPage Walk Caches”…”�”}”(hjüh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÐubhŒ to speed up these translations.”…”�”}”(hjÐh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hj¿h²hubhÞ)�”}”(hX6When CPU accesses a memory location, it provides a virtual address to the MMU, which checks if there is the existing translation in the TLB or in the Page Walk Caches (on architectures that support them). If no translation is found, MMU uses the page walks to determine the physical address and create the map.”h]”hX6When CPU accesses a memory location, it provides a virtual address to the MMU, which checks if there is the existing translation in the TLB or in the Page Walk Caches (on architectures that support them). If no translation is found, MMU uses the page walks to determine the physical address and create the map.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¥hj¿h²hubhÞ)�”}”(hŒáThe dirty bit for a page is set (i.e., turned on) when the page is written to. Each page of memory has associated permission and dirty bits. The latter indicate that the page has been modified since it was loaded into memory.”h]”hŒáThe dirty bit for a page is set (i.e., turned on) when the page is written to. Each page of memory has associated permission and dirty bits. The latter indicate that the page has been modified since it was loaded into memory.”…”�”}”(hj"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kªhj¿h²hubhÞ)�”}”(hŒ†If nothing prevents it, eventually the physical memory can be accessed and the requested operation on the physical frame is performed.”h]”hŒ†If nothing prevents it, eventually the physical memory can be accessed and the requested operation on the physical frame is performed.”…”�”}”(hj0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K®hj¿h²hubhÞ)�”}”(hŒåThere are several reasons why the MMU can't find certain translations. It could happen because the CPU is trying to access memory that the current task is not permitted to, or because the data is not present into physical memory.”h]”hŒçThere are several reasons why the MMU can’t find certain translations. It could happen because the CPU is trying to access memory that the current task is not permitted to, or because the data is not present into physical memory.”…”�”}”(hj>h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K±hj¿h²hubhÞ)�”}”(hŒËWhen these conditions happen, the MMU triggers page faults, which are types of exceptions that signal the CPU to pause the current execution and run a special function to handle the mentioned exceptions.”h]”hŒËWhen these conditions happen, the MMU triggers page faults, which are types of exceptions that signal the CPU to pause the current execution and run a special function to handle the mentioned exceptions.”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kµhj¿h²hubhÞ)�”}”(hX<There are common and expected causes of page faults. These are triggered by process management optimization techniques called "Lazy Allocation" and "Copy-on-Write". Page faults may also happen when frames have been swapped out to persistent storage (swap partition or file) and evicted from their physical locations.”h]”hXDThere are common and expected causes of page faults. These are triggered by process management optimization techniques called “Lazy Allocationâ€� and “Copy-on-Writeâ€�. Page faults may also happen when frames have been swapped out to persistent storage (swap partition or file) and evicted from their physical locations.”…”�”}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¹hj¿h²hubhÞ)�”}”(hXThese techniques improve memory efficiency, reduce latency, and minimize space occupation. This document won't go deeper into the details of "Lazy Allocation" and "Copy-on-Write" because these subjects are out of scope as they belong to Process Address Management.”h]”hXThese techniques improve memory efficiency, reduce latency, and minimize space occupation. This document won’t go deeper into the details of “Lazy Allocationâ€� and “Copy-on-Writeâ€� because these subjects are out of scope as they belong to Process Address Management.”…”�”}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¿hj¿h²hubhÞ)�”}”(hŒ¢Swapping differentiates itself from the other mentioned techniques because it's undesirable since it's performed as a means to reduce memory under heavy pressure.”h]”hŒ¦Swapping differentiates itself from the other mentioned techniques because it’s undesirable since it’s performed as a means to reduce memory under heavy pressure.”…”�”}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÄhj¿h²hubhÞ)�”}”(hX°Swapping can't work for memory mapped by kernel logical addresses. These are a subset of the kernel virtual space that directly maps a contiguous range of physical memory. Given any logical address, its physical address is determined with simple arithmetic on an offset. Accesses to logical addresses are fast because they avoid the need for complex page table lookups at the expenses of frames not being evictable and pageable out.”h]”hX²Swapping can’t work for memory mapped by kernel logical addresses. These are a subset of the kernel virtual space that directly maps a contiguous range of physical memory. Given any logical address, its physical address is determined with simple arithmetic on an offset. Accesses to logical addresses are fast because they avoid the need for complex page table lookups at the expenses of frames not being evictable and pageable out.”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÈhj¿h²hubhÞ)�”}”(hŒðIf the kernel fails to make room for the data that must be present in the physical frames, the kernel invokes the out-of-memory (OOM) killer to make room by terminating lower priority processes until pressure reduces under a safe threshold.”h]”hŒðIf the kernel fails to make room for the data that must be present in the physical frames, the kernel invokes the out-of-memory (OOM) killer to make room by terminating lower priority processes until pressure reduces under a safe threshold.”…”�”}”(hj’h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÏhj¿h²hubhÞ)�”}”(hXSAdditionally, page faults may be also caused by code bugs or by maliciously crafted addresses that the CPU is instructed to access. A thread of a process could use instructions to address (non-shared) memory which does not belong to its own address space, or could try to execute an instruction that wants to write to a read-only location.”h]”hXSAdditionally, page faults may be also caused by code bugs or by maliciously crafted addresses that the CPU is instructed to access. A thread of a process could use instructions to address (non-shared) memory which does not belong to its own address space, or could try to execute an instruction that wants to write to a read-only location.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÔhj¿h²hubhÞ)�”}”(hŒâIf the above-mentioned conditions happen in user-space, the kernel sends a `Segmentation Fault` (SIGSEGV) signal to the current thread. That signal usually causes the termination of the thread and of the process it belongs to.”h]”(hŒKIf the above-mentioned conditions happen in user-space, the kernel sends a ”…”�”}”(hj®h²hh³Nh´Nubj8)�”}”(hŒ`Segmentation Fault`”h]”hŒSegmentation Fault”…”�”}”(hj¶h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj®ubhŒƒ (SIGSEGV) signal to the current thread. That signal usually causes the termination of the thread and of the process it belongs to.”…”�”}”(hj®h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÚhj¿h²hubhÞ)�”}”(hX)This document is going to simplify and show an high altitude view of how the Linux kernel handles these page faults, creates tables and tables' entries, check if memory is present and, if not, requests to load data from persistent storage or from other devices, and updates the MMU and its caches.”h]”hX+This document is going to simplify and show an high altitude view of how the Linux kernel handles these page faults, creates tables and tables’ entries, check if memory is present and, if not, requests to load data from persistent storage or from other devices, and updates the MMU and its caches.”…”�”}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÞhj¿h²hubhÞ)�”}”(hŒØThe first steps are architecture dependent. Most architectures jump to `do_page_fault()`, whereas the x86 interrupt handler is defined by the `DEFINE_IDTENTRY_RAW_ERRORCODE()` macro which calls `handle_page_fault()`.”h]”(hŒGThe first steps are architecture dependent. Most architectures jump to ”…”�”}”(hjÜh²hh³Nh´Nubj8)�”}”(hŒ`do_page_fault()`”h]”hŒdo_page_fault()”…”�”}”(hjäh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÜubhŒ6, whereas the x86 interrupt handler is defined by the ”…”�”}”(hjÜh²hh³Nh´Nubj8)�”}”(hŒ!`DEFINE_IDTENTRY_RAW_ERRORCODE()`”h]”hŒDEFINE_IDTENTRY_RAW_ERRORCODE()”…”�”}”(hjöh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÜubhŒ macro which calls ”…”�”}”(hjÜh²hh³Nh´Nubj8)�”}”(hŒ`handle_page_fault()`”h]”hŒhandle_page_fault()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÜubhŒ.”…”�”}”(hjÜh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kãhj¿h²hubhÞ)�”}”(hŒÑWhatever the routes, all architectures end up to the invocation of `handle_mm_fault()` which, in turn, (likely) ends up calling `__handle_mm_fault()` to carry out the actual work of allocating the page tables.”h]”(hŒCWhatever the routes, all architectures end up to the invocation of ”…”�”}”(hj h²hh³Nh´Nubj8)�”}”(hŒ`handle_mm_fault()`”h]”hŒhandle_mm_fault()”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj ubhŒ* which, in turn, (likely) ends up calling ”…”�”}”(hj h²hh³Nh´Nubj8)�”}”(hŒ`__handle_mm_fault()`”h]”hŒ__handle_mm_fault()”…”�”}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj ubhŒ< to carry out the actual work of allocating the page tables.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kçhj¿h²hubhÞ)�”}”(hXhThe unfortunate case of not being able to call `__handle_mm_fault()` means that the virtual address is pointing to areas of physical memory which are not permitted to be accessed (at least from the current context). This condition resolves to the kernel sending the above-mentioned SIGSEGV signal to the process and leads to the consequences already explained.”h]”(hŒ/The unfortunate case of not being able to call ”…”�”}”(hjRh²hh³Nh´Nubj8)�”}”(hŒ`__handle_mm_fault()`”h]”hŒ__handle_mm_fault()”…”�”}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjRubhX$ means that the virtual address is pointing to areas of physical memory which are not permitted to be accessed (at least from the current context). This condition resolves to the kernel sending the above-mentioned SIGSEGV signal to the process and leads to the consequences already explained.”…”�”}”(hjRh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kìhj¿h²hubhÞ)�”}”(hŒ´`__handle_mm_fault()` carries out its work by calling several functions to find the entry's offsets of the upper layers of the page tables and allocate the tables that it may need.”h]”(j8)�”}”(hŒ`__handle_mm_fault()`”h]”hŒ__handle_mm_fault()”…”�”}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjrubhŒ¡ carries out its work by calling several functions to find the entry’s offsets of the upper layers of the page tables and allocate the tables that it may need.”…”�”}”(hjrh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kòhj¿h²hubhÞ)�”}”(hX@The functions that look for the offset have names like `*_offset()`, where the "*" is for pgd, p4d, pud, pmd, pte; instead the functions to allocate the corresponding tables, layer by layer, are called `*_alloc`, using the above-mentioned convention to name them after the corresponding types of tables in the hierarchy.”h]”(hŒ7The functions that look for the offset have names like ”…”�”}”(hjŽh²hh³Nh´Nubj8)�”}”(hŒ `*_offset()`”h]”hŒ *_offset()”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjŽubhŒ‹, where the “*â€� is for pgd, p4d, pud, pmd, pte; instead the functions to allocate the corresponding tables, layer by layer, are called ”…”�”}”(hjŽh²hh³Nh´Nubj8)�”}”(hŒ `*_alloc`”h]”hŒ*_alloc”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjŽubhŒm, using the above-mentioned convention to name them after the corresponding types of tables in the hierarchy.”…”�”}”(hjŽh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Köhj¿h²hubhÞ)�”}”(hŒLThe page table walk may end at one of the middle or upper layers (PMD, PUD).”h]”hŒLThe page table walk may end at one of the middle or upper layers (PMD, PUD).”…”�”}”(hjÀh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kühj¿h²hubhÞ)�”}”(hXsLinux supports larger page sizes than the usual 4KB (i.e., the so called `huge pages`). When using these kinds of larger pages, higher level pages can directly map them, with no need to use lower level page entries (PTE). Huge pages contain large contiguous physical regions that usually span from 2MB to 1GB. They are respectively mapped by the PMD and PUD page entries.”h]”(hŒILinux supports larger page sizes than the usual 4KB (i.e., the so called ”…”�”}”(hjÎh²hh³Nh´Nubj8)�”}”(hŒ `huge pages`”h]”hŒ huge pages”…”�”}”(hjÖh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjÎubhX). When using these kinds of larger pages, higher level pages can directly map them, with no need to use lower level page entries (PTE). Huge pages contain large contiguous physical regions that usually span from 2MB to 1GB. They are respectively mapped by the PMD and PUD page entries.”…”�”}”(hjÎh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kþhj¿h²hubhÞ)�”}”(hXThe huge pages bring with them several benefits like reduced TLB pressure, reduced page table overhead, memory allocation efficiency, and performance improvement for certain workloads. However, these benefits come with trade-offs, like wasted memory and allocation challenges.”h]”hXThe huge pages bring with them several benefits like reduced TLB pressure, reduced page table overhead, memory allocation efficiency, and performance improvement for certain workloads. However, these benefits come with trade-offs, like wasted memory and allocation challenges.”…”�”}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Mhj¿h²hubhÞ)�”}”(hX>At the very end of the walk with allocations, if it didn't return errors, `__handle_mm_fault()` finally calls `handle_pte_fault()`, which via `do_fault()` performs one of `do_read_fault()`, `do_cow_fault()`, `do_shared_fault()`. "read", "cow", "shared" give hints about the reasons and the kind of fault it's handling.”h]”(hŒLAt the very end of the walk with allocations, if it didn’t return errors, ”…”�”}”(hjüh²hh³Nh´Nubj8)�”}”(hŒ`__handle_mm_fault()`”h]”hŒ__handle_mm_fault()”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjüubhŒ finally calls ”…”�”}”(hjüh²hh³Nh´Nubj8)�”}”(hŒ`handle_pte_fault()`”h]”hŒhandle_pte_fault()”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjüubhŒ , which via ”…”�”}”(hjüh²hh³Nh´Nubj8)�”}”(hŒ `do_fault()`”h]”hŒ do_fault()”…”�”}”(hj( h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjüubhŒ performs one of ”…”�”}”(hjüh²hh³Nh´Nubj8)�”}”(hŒ`do_read_fault()`”h]”hŒdo_read_fault()”…”�”}”(hj: h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjüubhŒ, ”…”�”}”(hjüh²hh³Nh´Nubj8)�”}”(hŒ`do_cow_fault()`”h]”hŒdo_cow_fault()”…”�”}”(hjL h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjüubhŒ, ”…”�”}”hjüsbj8)�”}”(hŒ`do_shared_fault()`”h]”hŒdo_shared_fault()”…”�”}”(hj^ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hjüubhŒi. “readâ€�, “cowâ€�, “sharedâ€� give hints about the reasons and the kind of fault it’s handling.”…”�”}”(hjüh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´M hj¿h²hubhÞ)�”}”(hŒèThe actual implementation of the workflow is very complex. Its design allows Linux to handle page faults in a way that is tailored to the specific characteristics of each architecture, while still sharing a common overall structure.”h]”hŒèThe actual implementation of the workflow is very complex. Its design allows Linux to handle page faults in a way that is tailored to the specific characteristics of each architecture, while still sharing a common overall structure.”…”�”}”(hjv h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Mhj¿h²hubhÞ)�”}”(hŒÊTo conclude this high altitude view of how Linux handles page faults, let's add that the page faults handler can be disabled and enabled respectively with `pagefault_disable()` and `pagefault_enable()`.”h]”(hŒ�To conclude this high altitude view of how Linux handles page faults, let’s add that the page faults handler can be disabled and enabled respectively with ”…”�”}”(hj„ h²hh³Nh´Nubj8)�”}”(hŒ`pagefault_disable()`”h]”hŒpagefault_disable()”…”�”}”(hjŒ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj„ ubhŒ and ”…”�”}”(hj„ h²hh³Nh´Nubj8)�”}”(hŒ`pagefault_enable()`”h]”hŒpagefault_enable()”…”�”}”(hjž h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j7hj„ ubhŒ.”…”�”}”(hj„ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Mhj¿h²hubhÞ)�”}”(hŒ•Several code paths make use of the latter two functions because they need to disable traps into the page faults handler, mostly to prevent deadlocks.”h]”hŒ•Several code paths make use of the latter two functions because they need to disable traps into the page faults handler, mostly to prevent deadlocks.”…”�”}”(hj¶ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Mhj¿h²hubeh}”(h]”Œmmu-tlb-and-page-faults”ah ]”h"]”Œmmu, tlb, and page faults”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´Kžubeh}”(h]”Œ page-tables”ah ]”h"]”Œ page tables”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Ñ jÎ j¼j¹jÉ jÆ uŒ nametypes”}”(jÑ ‰j¼‰jÉ ‰uh}”(jÎ hÊj¹jxjÆ 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.