{"id":52,"date":"2022-04-21T21:21:18","date_gmt":"2022-04-22T04:21:18","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/usageoptions\/?p=52"},"modified":"2022-04-21T21:29:20","modified_gmt":"2022-04-22T04:29:20","slug":"linux-kernel-series-highmem","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/usageoptions\/2022\/04\/21\/linux-kernel-series-highmem\/","title":{"rendered":"Linux kernel series: HIGHMEM"},"content":{"rendered":"\n<p style=\"font-size:1rem\">This is the second post in the Linux kernel series. The <a href=\"https:\/\/blogs.oregonstate.edu\/usageoptions\/2022\/04\/14\/linux-kernel-series-memblock\/\">first part of the series<\/a> was about <code>memblock<\/code>. This week, the topic is <code>HIGHMEM<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" style=\"font-size:1.75rem\">What is HIGHMEM?<\/h2>\n\n\n\n<p style=\"font-size:1rem\">The Linux kernel <a href=\"https:\/\/pages.cs.wisc.edu\/~remzi\/OSTEP\/vm-intro.pdf\">virtualizes<\/a> its memory. Virtual memory addresses, which can be used by programs, are mapped to physical memory addresses. When the size of the physical memory exceeds the (maximum) size of the virtual memory, it is not possible for the kernel to map every physical address to a virtual address. So the kernel uses temporary mappings when it wants to access part of the physical memory that is not mapped to a permanent virtual memory address. The part of physical memory that does not have a permanent mapping to a virtual address is called high memory (<code>HIGHMEM<\/code>).<sup><a href=\"#references\">[1]<\/a><\/sup><\/p>\n\n\n\n<div class=\"wp-block-columns has-white-background-color has-background is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<figure class=\"wp-block-image size-large is-style-default\"><img decoding=\"async\" src=\"https:\/\/linux-kernel-labs.github.io\/refs\/heads\/master\/_images\/kernel-virtmem-map.png\" alt=\"\" \/><figcaption>Source: <a href=\"https:\/\/linux-kernel-labs.github.io\/refs\/heads\/master\/labs\/memory_mapping.html#overview\">https:\/\/linux-kernel-labs.github.io\/refs\/heads\/master\/labs\/memory_mapping.html#overview<\/a><\/figcaption><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p style=\"font-size:1rem\"><code>HIGHMEM<\/code> is often needed in 32 bit systems. A 32 bit address can represent at most 2<sup>32<\/sup> = 4,294,967,296 different addresses, which is approximately 4 GB (or <a href=\"https:\/\/en.wikipedia.org\/wiki\/Byte#Multiple-byte_units\">exactly 4 GiB<\/a>). But many systems have more than 4 GB of physical memory.<\/p>\n\n\n\n<p style=\"font-size:1rem\">The available virtual memory space has to be divided between kernel space and user space. A common split is 3 : 1 user space : kernel space, which would mean 3 GB for user space and 1 GB for kernel space on a 32 bit system. The part of kernel space that has a direct mapping to a permanent physical memory is called <code>LOWMEM<\/code>. <code>LOWMEM<\/code> is contiguously mapped in physical memory.<sup><a href=\"#references\">[2]<\/a><\/sup><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" style=\"font-size:1.75rem\">Creating Temporary Maps<\/h2>\n\n\n\n<p style=\"font-size:1rem\">There are several different functions for creating temporary virtual maps.<sup><a href=\"#references\">[2]<\/a><\/sup><\/p>\n\n\n\n<pre class=\"wp-block-code has-light-gray-background-color has-background\" style=\"font-size:1rem\"><code><strong>vmap()<\/strong> : used to map multiple physical pages into a contiguous virtual address space for a long duration\n<strong>kmap()<\/strong> : used to map a single physical page for a short duration. Prone to deadlocks when nested, and not recommended in new code\n<strong>kmap_atomic()<\/strong> : used to map a single physical page for a very short duration. It performs well because it is restricted to the CPU that issued it, but the issuing task must stay on the same CPU until it finishes.\n<strong>kmap_local_page()<\/strong> : recently developed as a replacement for kmap(). It creates a mapping that is restricted to local use by a single thread of execution. This function is preferred over the other functions and should be used when possible.<sup><a href=\"#references\">&#091;3]<\/a><\/sup><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"references\" style=\"font-size:1.75rem\">References<\/h2>\n\n\n\n<ol class=\"wp-block-list\" style=\"font-size:1rem\"><li><a href=\"https:\/\/www.kernel.org\/doc\/html\/latest\/vm\/highmem.html\">High Memory Handling \u2014 The Linux Kernel documentation<\/a><\/li><li><a href=\"https:\/\/linux-kernel-labs.github.io\/refs\/heads\/master\/labs\/memory_mapping.html\">Memory Mapping \u2014 The Linux Kernel documentation<\/a><\/li><li><a href=\"https:\/\/lore.kernel.org\/lkml\/?q=kmap_local_page\">LKML Mailing List<\/a><\/li><\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This is the second post in the Linux kernel series. The first part of the series was about memblock. This week, the topic is HIGHMEM. What is HIGHMEM? The Linux kernel virtualizes its memory. Virtual memory addresses, which can be &hellip; <a href=\"https:\/\/blogs.oregonstate.edu\/usageoptions\/2022\/04\/21\/linux-kernel-series-highmem\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":12377,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[17,18,3,4],"class_list":["post-52","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c","tag-highmem","tag-linux","tag-outreachy"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/posts\/52","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/users\/12377"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/comments?post=52"}],"version-history":[{"count":11,"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/posts\/52\/revisions"}],"predecessor-version":[{"id":65,"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/posts\/52\/revisions\/65"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/media?parent=52"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/categories?post=52"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/usageoptions\/wp-json\/wp\/v2\/tags?post=52"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}