<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/c/coreboot/+/30119">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">arch/x86/mmu: Port armv8 MMU to x86_64<br><br>Add functions to setup page tables for long mode.<br>Required to support x86_64, as the MMU is always active.<br><br>Tested on qemu.<br><br>Change-Id: I6e8b46e65925823a84b8ccd647c7d6848aa20992<br>Signed-off-by: Patrick Rudolph <siro@das-labor.org><br>---<br>M src/arch/x86/Kconfig<br>A src/arch/x86/include/arch/mmu.h<br>A src/arch/x86/mmu.c<br>M src/commonlib/include/commonlib/cbmem_id.h<br>4 files changed, 486 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/19/30119/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig</span><br><span>index 7c8371e..11389c0 100644</span><br><span>--- a/src/arch/x86/Kconfig</span><br><span>+++ b/src/arch/x86/Kconfig</span><br><span>@@ -317,6 +317,13 @@</span><br><span>         help</span><br><span>           The number of 4KiB pages that should be pre-allocated for page tables.</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+config NUM_PAGE_TABLE_PAGES</span><br><span style="color: hsl(120, 100%, 40%);">+     int</span><br><span style="color: hsl(120, 100%, 40%);">+   default 128</span><br><span style="color: hsl(120, 100%, 40%);">+   depends on ARCH_X86</span><br><span style="color: hsl(120, 100%, 40%);">+   help</span><br><span style="color: hsl(120, 100%, 40%);">+    The number of 4KiB pages that should be available for ramstage.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # Provide the interrupt handlers to every stage. Not all</span><br><span> # stages may take advantage.</span><br><span> config IDT_IN_EVERY_STAGE</span><br><span>diff --git a/src/arch/x86/include/arch/mmu.h b/src/arch/x86/include/arch/mmu.h</span><br><span>new file mode 100644</span><br><span>index 0000000..4cb0354</span><br><span>--- /dev/null</span><br><span>+++ b/src/arch/x86/include/arch/mmu.h</span><br><span>@@ -0,0 +1,103 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2014 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __ARCH_X86_MMU_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __ARCH_X86_MMU_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <types.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Memory attributes for mmap regions</span><br><span style="color: hsl(120, 100%, 40%);">+ * These attributes act as tag values for memrange regions</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Descriptor attributes */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DESC_MASK 0xeaf</span><br><span style="color: hsl(120, 100%, 40%);">+#define INVALID_DESC 0</span><br><span style="color: hsl(120, 100%, 40%);">+#define TABLE_DESC 0x623</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAGE_DESC 0x4a3</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_DESC 0x2a3</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define AVAIL_SHIFT 9</span><br><span style="color: hsl(120, 100%, 40%);">+#define AVAIL_MASK (7 << AVAIL_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define AVAIL_INVAL 0</span><br><span style="color: hsl(120, 100%, 40%);">+#define AVAIL_TABLE 3</span><br><span style="color: hsl(120, 100%, 40%);">+#define AVAIL_PAGE 2</span><br><span style="color: hsl(120, 100%, 40%);">+#define AVAIL_BLOCK 1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Block descriptor */</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_NS                   (1 << 5)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_AP_RW                (0 << 7)</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_AP_RO                (1 << 7)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_ACCESS               (1 << 10)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_XN                   (1ULL << 54)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_SH_SHIFT                 (8)</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_SH_NON_SHAREABLE         (0 << BLOCK_SH_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_SH_UNPREDICTABLE         (1 << BLOCK_SH_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_SH_OUTER_SHAREABLE       (2 << BLOCK_SH_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_SH_INNER_SHAREABLE       (3 << BLOCK_SH_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Sentinel descriptor to mark first PTE of an unused table. It must be a value</span><br><span style="color: hsl(120, 100%, 40%);">+ * that cannot occur naturally as part of a page table. (Bits [1:0] = 0b00 makes</span><br><span style="color: hsl(120, 100%, 40%);">+ * this an unmapped page, but some page attribute bits are still set.) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define UNUSED_DESC                0x6EbAAD0BBADbA000ULL</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* XLAT Table Init Attributes */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define VA_START                   0x0</span><br><span style="color: hsl(120, 100%, 40%);">+#define BITS_PER_VA                48</span><br><span style="color: hsl(120, 100%, 40%);">+/* Granule size of 4KB is being used */</span><br><span style="color: hsl(120, 100%, 40%);">+#define GRANULE_SIZE_SHIFT         12</span><br><span style="color: hsl(120, 100%, 40%);">+#define GRANULE_SIZE               (1 << GRANULE_SIZE_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define XLAT_ADDR_MASK             ((1ULL << BITS_PER_VA) - GRANULE_SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+#define GRANULE_SIZE_MASK          ((1ULL << GRANULE_SIZE_SHIFT) - 1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BITS_RESOLVED_PER_LVL (GRANULE_SIZE_SHIFT - 3)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L0_ADDR_SHIFT         (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 3)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L1_ADDR_SHIFT         (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 2)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L2_ADDR_SHIFT         (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L3_ADDR_SHIFT         (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define L0_ADDR_MASK   (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L0_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L1_ADDR_MASK   (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L1_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L2_ADDR_MASK   (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L2_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L3_ADDR_MASK   (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L3_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* These macros give the size of the region addressed by each entry of a xlat</span><br><span style="color: hsl(120, 100%, 40%);">+   table at any given level */</span><br><span style="color: hsl(120, 100%, 40%);">+#define L3_XLAT_SIZE               (1ULL << L3_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L2_XLAT_SIZE               (1ULL << L2_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L1_XLAT_SIZE               (1ULL << L1_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define L0_XLAT_SIZE               (1ULL << L0_ADDR_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAT_UC            0</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAT_WC               1</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAT_WT               4</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAT_WP               5</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAT_WB               6</span><br><span style="color: hsl(120, 100%, 40%);">+#define PAT_UC_MINUS 7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Initialize MMU registers and page table memory region. */</span><br><span style="color: hsl(120, 100%, 40%);">+void mmu_init(void *new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+/* Install page tables */</span><br><span style="color: hsl(120, 100%, 40%);">+void mmu_enable(void *new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+void mmu_config_range(uint64_t start, uint64_t size, uint64_t tag);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __ARCH_X86_MMU_H__ */</span><br><span>diff --git a/src/arch/x86/mmu.c b/src/arch/x86/mmu.c</span><br><span>new file mode 100644</span><br><span>index 0000000..39802f0</span><br><span>--- /dev/null</span><br><span>+++ b/src/arch/x86/mmu.c</span><br><span>@@ -0,0 +1,375 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2014 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+ * modification, are permitted provided that the following conditions</span><br><span style="color: hsl(120, 100%, 40%);">+ * are met:</span><br><span style="color: hsl(120, 100%, 40%);">+ * 1. Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+ *    notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * 2. Redistributions in binary form must reproduce the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+ *    notice, this list of conditions and the following disclaimer in the</span><br><span style="color: hsl(120, 100%, 40%);">+ *    documentation and/or other materials provided with the distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+ * 3. The name of the author may not be used to endorse or promote products</span><br><span style="color: hsl(120, 100%, 40%);">+ *    derived from this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND</span><br><span style="color: hsl(120, 100%, 40%);">+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span><br><span style="color: hsl(120, 100%, 40%);">+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span><br><span style="color: hsl(120, 100%, 40%);">+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE</span><br><span style="color: hsl(120, 100%, 40%);">+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span><br><span style="color: hsl(120, 100%, 40%);">+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS</span><br><span style="color: hsl(120, 100%, 40%);">+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)</span><br><span style="color: hsl(120, 100%, 40%);">+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY</span><br><span style="color: hsl(120, 100%, 40%);">+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF</span><br><span style="color: hsl(120, 100%, 40%);">+ * SUCH DAMAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <symbols.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/mmu.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/cache.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cpu/x86/msr.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cbmem.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This just caches the next free table slot (okay to do since they fill up from</span><br><span style="color: hsl(120, 100%, 40%);">+ * bottom to top and can never be freed up again). It will reset to its initial</span><br><span style="color: hsl(120, 100%, 40%);">+ * value on stage transition, so we still need to check it for UNUSED_DESC. */</span><br><span style="color: hsl(120, 100%, 40%);">+static CAR_GLOBAL uint64_t *next_free_table;</span><br><span style="color: hsl(120, 100%, 40%);">+static CAR_GLOBAL uint64_t *page_tables;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_PRES (1ULL << 0)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_RW   (1ULL << 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_US   (1ULL << 2)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_PWT  (1ULL << 3)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_PCD  (1ULL << 4)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_A    (1ULL << 5)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_D    (1ULL << 6)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_PAT  (1ULL << 7)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_G    (1ULL << 8)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PTE_XD   (1ULL << 63)</span><br><span style="color: hsl(120, 100%, 40%);">+#define PDE_PS   (1ULL << 7)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_INDEX_MASK (PTE_PWT | PTE_PCD | PTE_PRES | PTE_RW | PTE_A | PTE_D)</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_INDEX_SHIFT 0</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_INDEX_MEM_NORMAL (PTE_PRES | PTE_RW | PTE_A | PTE_D)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void print_tag(int level, uint64_t pat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (pat) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_UC:</span><br><span style="color: hsl(120, 100%, 40%);">+          printk(level, "UC\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_WC:</span><br><span style="color: hsl(120, 100%, 40%);">+          printk(level, "WC\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_WT:</span><br><span style="color: hsl(120, 100%, 40%);">+          printk(level, "WT\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_WP:</span><br><span style="color: hsl(120, 100%, 40%);">+          printk(level, "WP\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_WB:</span><br><span style="color: hsl(120, 100%, 40%);">+          printk(level, "WB\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_UC_MINUS:</span><br><span style="color: hsl(120, 100%, 40%);">+            printk(level, "UC-\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t pte_pat_flags(unsigned long pat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (pat) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case PAT_UC:</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0 | PTE_PCD | PTE_PWT;</span><br><span style="color: hsl(120, 100%, 40%);">+ case PAT_WC:</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0 | 0 | PTE_PWT;</span><br><span style="color: hsl(120, 100%, 40%);">+       case PAT_WT:</span><br><span style="color: hsl(120, 100%, 40%);">+          return PTE_PAT | PTE_PCD | PTE_PWT;</span><br><span style="color: hsl(120, 100%, 40%);">+   case PAT_WP:</span><br><span style="color: hsl(120, 100%, 40%);">+          return PTE_PAT | 0 | PTE_PWT;</span><br><span style="color: hsl(120, 100%, 40%);">+ case PAT_WB:</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0 | 0 | 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     case PAT_UC_MINUS:</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0 | PTE_PCD | 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       default:</span><br><span style="color: hsl(120, 100%, 40%);">+              printk(BIOS_ERR, "MMU: PTE PAT defaulting to WB: %lx\n", pat);</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0 | 0 | 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t *pagetable(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return car_get_var(page_tables);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t *epagetable(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return (uint64_t *)((u8 *)car_get_var(page_tables) +</span><br><span style="color: hsl(120, 100%, 40%);">+          (CONFIG_NUM_PAGE_TABLE_PAGES * 4 * KiB));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : get_block_attr</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Get block descriptor attributes based on the value of tag in memrange</span><br><span style="color: hsl(120, 100%, 40%);">+ * region</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t get_block_attr(unsigned long tag, bool ps)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint64_t flags = PTE_PRES | PTE_RW | PTE_US | PTE_A | PTE_D;</span><br><span style="color: hsl(120, 100%, 40%);">+  flags |= pte_pat_flags(tag);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ps) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (flags & PTE_PAT) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    /* If PS=1 PAT is at position 12 instead of 7 */</span><br><span style="color: hsl(120, 100%, 40%);">+                      flags &= ~PTE_PAT;</span><br><span style="color: hsl(120, 100%, 40%);">+                        flags |= (PTE_PAT << 5);</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             flags |= PDE_PS;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     return flags;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : setup_new_table</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Get next free table from pagetable and set it up to match</span><br><span style="color: hsl(120, 100%, 40%);">+ *        old parent entry.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t *setup_new_table(uint64_t desc, uint64_t xlat_size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint64_t *nft = car_get_var(next_free_table);</span><br><span style="color: hsl(120, 100%, 40%);">+ while (nft[0] != UNUSED_DESC) {</span><br><span style="color: hsl(120, 100%, 40%);">+               car_set_var(next_free_table, car_get_var(next_free_table) +</span><br><span style="color: hsl(120, 100%, 40%);">+                       GRANULE_SIZE/sizeof(*next_free_table));</span><br><span style="color: hsl(120, 100%, 40%);">+           nft = car_get_var(next_free_table);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (epagetable() - car_get_var(next_free_table) <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      die("Ran out of page table space!");</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   uint64_t frame_base = desc & XLAT_ADDR_MASK;</span><br><span style="color: hsl(120, 100%, 40%);">+      printk(BIOS_DEBUG, "MMU: Backing address range [0x%llx:0x%llx) with "</span><br><span style="color: hsl(120, 100%, 40%);">+              "new page table @%p\n", frame_base, frame_base +</span><br><span style="color: hsl(120, 100%, 40%);">+            (xlat_size << BITS_RESOLVED_PER_LVL), nft);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (desc == INVALID_DESC) {</span><br><span style="color: hsl(120, 100%, 40%);">+           memset(nft, 0, GRANULE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Can reuse old parent entry, but may need to adjust type. */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (xlat_size == L3_XLAT_SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+                        desc |= PAGE_DESC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            for (; i < GRANULE_SIZE/sizeof(*next_free_table); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   nft[i] = desc;</span><br><span style="color: hsl(120, 100%, 40%);">+                        desc += xlat_size;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return nft;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func: get_next_level_table</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc: Check if the table entry is a valid descriptor. If not, initialize new</span><br><span style="color: hsl(120, 100%, 40%);">+ * table, update the entry and return the table addr. If valid, return the addr</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t *get_next_level_table(uint64_t *ptr, size_t xlat_size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     uint64_t desc = *ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if ((desc & DESC_MASK) != TABLE_DESC) {</span><br><span style="color: hsl(120, 100%, 40%);">+           uint64_t *new_table = setup_new_table(desc, xlat_size);</span><br><span style="color: hsl(120, 100%, 40%);">+               desc = ((uintptr_t)new_table) | TABLE_DESC;</span><br><span style="color: hsl(120, 100%, 40%);">+           *ptr = desc;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     return (uint64_t *)(uintptr_t)(desc & XLAT_ADDR_MASK);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ Func : init_xlat_table</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Given a base address and size, it identifies the indices within</span><br><span style="color: hsl(120, 100%, 40%);">+ * different level XLAT tables which map the given base addr. Similar to table</span><br><span style="color: hsl(120, 100%, 40%);">+ * walk, except that all invalid entries during the walk are updated</span><br><span style="color: hsl(120, 100%, 40%);">+ * accordingly. On success, it returns the size of the block/page addressed by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the final table.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t init_xlat_table(uint64_t base_addr,</span><br><span style="color: hsl(120, 100%, 40%);">+                          uint64_t size,</span><br><span style="color: hsl(120, 100%, 40%);">+                                uint64_t tag)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint64_t l0_index = (base_addr & L0_ADDR_MASK) >> L0_ADDR_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint64_t l1_index = (base_addr & L1_ADDR_MASK) >> L1_ADDR_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint64_t l2_index = (base_addr & L2_ADDR_MASK) >> L2_ADDR_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint64_t l3_index = (base_addr & L3_ADDR_MASK) >> L3_ADDR_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint64_t *table = pagetable();</span><br><span style="color: hsl(120, 100%, 40%);">+        uint64_t desc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* check if CPU supports 1GB huge tables */</span><br><span style="color: hsl(120, 100%, 40%);">+   const bool hugepage_1gb = !!(cpuid_edx(0x80000001) & (1 << 26));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* L0 entry stores a table descriptor (doesn't support blocks) */</span><br><span style="color: hsl(120, 100%, 40%);">+ table = get_next_level_table(&table[l0_index], L1_XLAT_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* L1 table lookup */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((size >= L1_XLAT_SIZE) &&</span><br><span style="color: hsl(120, 100%, 40%);">+          IS_ALIGNED(base_addr, (1UL << L1_ADDR_SHIFT)) &&</span><br><span style="color: hsl(120, 100%, 40%);">+        hugepage_1gb) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /* If block address is aligned and size is greater than</span><br><span style="color: hsl(120, 100%, 40%);">+                       * or equal to size addressed by each L1 entry, we can</span><br><span style="color: hsl(120, 100%, 40%);">+                 * directly store a block desc */</span><br><span style="color: hsl(120, 100%, 40%);">+              desc = base_addr | BLOCK_DESC | get_block_attr(tag, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+               table[l1_index] = desc;</span><br><span style="color: hsl(120, 100%, 40%);">+               /* L2 lookup is not required */</span><br><span style="color: hsl(120, 100%, 40%);">+               return L1_XLAT_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* L1 entry stores a table descriptor */</span><br><span style="color: hsl(120, 100%, 40%);">+      table = get_next_level_table(&table[l1_index], L2_XLAT_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* L2 table lookup */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((size >= L2_XLAT_SIZE) &&</span><br><span style="color: hsl(120, 100%, 40%);">+          IS_ALIGNED(base_addr, (1UL << L2_ADDR_SHIFT))) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* If block address is aligned and size is greater than</span><br><span style="color: hsl(120, 100%, 40%);">+                * or equal to size addressed by each L2 entry, we can</span><br><span style="color: hsl(120, 100%, 40%);">+                 * directly store a block desc */</span><br><span style="color: hsl(120, 100%, 40%);">+             desc = base_addr | BLOCK_DESC | get_block_attr(tag, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+               table[l2_index] = desc;</span><br><span style="color: hsl(120, 100%, 40%);">+               /* L3 lookup is not required */</span><br><span style="color: hsl(120, 100%, 40%);">+               return L2_XLAT_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* L2 entry stores a table descriptor */</span><br><span style="color: hsl(120, 100%, 40%);">+      table = get_next_level_table(&table[l2_index], L3_XLAT_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* L3 table lookup */</span><br><span style="color: hsl(120, 100%, 40%);">+ desc = base_addr | PAGE_DESC | get_block_attr(tag, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        table[l3_index] = desc;</span><br><span style="color: hsl(120, 100%, 40%);">+       return L3_XLAT_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : sanity_check</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Check address/size alignment of a table or page.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void sanity_check(uint64_t addr, uint64_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(!(addr & GRANULE_SIZE_MASK) &&</span><br><span style="color: hsl(120, 100%, 40%);">+            !(size & GRANULE_SIZE_MASK) &&</span><br><span style="color: hsl(120, 100%, 40%);">+            (addr + size < (1ULL << BITS_PER_VA)) &&</span><br><span style="color: hsl(120, 100%, 40%);">+             size >= GRANULE_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : get_pte</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Returns the page table entry governing a specific address. */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t get_pte(uint64_t addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int shift = L0_ADDR_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Using pointer here is OK, as _pagetable must be in 32bit space */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint64_t *pte = pagetable();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int index = ((uintptr_t)addr >> shift) &</span><br><span style="color: hsl(120, 100%, 40%);">+                        ((1ULL << BITS_RESOLVED_PER_LVL) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            if ((pte[index] & DESC_MASK) != TABLE_DESC ||</span><br><span style="color: hsl(120, 100%, 40%);">+                 shift <= GRANULE_SIZE_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+                   return pte[index];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          pte = (uint64_t *)(uintptr_t)(pte[index] & XLAT_ADDR_MASK);</span><br><span style="color: hsl(120, 100%, 40%);">+               shift -= BITS_RESOLVED_PER_LVL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : assert_correct_pagetable_mapping</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Asserts that mapping for addr matches the access type used by the</span><br><span style="color: hsl(120, 100%, 40%);">+ * page table walk (i.e. addr is correctly mapped to be part of the pagetable).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void assert_correct_pagetable_mapping(uint64_t addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     uint64_t pte = get_pte(addr);</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(((pte >> BLOCK_INDEX_SHIFT) & BLOCK_INDEX_MASK)</span><br><span style="color: hsl(120, 100%, 40%);">+             == BLOCK_INDEX_MEM_NORMAL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : mmu_config_range</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : This function repeatedly calls init_xlat_table with the base</span><br><span style="color: hsl(120, 100%, 40%);">+ * address. Based on size returned from init_xlat_table, base_addr is updated</span><br><span style="color: hsl(120, 100%, 40%);">+ * and subsequent calls are made for initializing the xlat table until the whole</span><br><span style="color: hsl(120, 100%, 40%);">+ * region is initialized.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void mmu_config_range(uint64_t start, uint64_t size, uint64_t tag)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint64_t base_addr = start;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint64_t temp_size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printk(BIOS_INFO, "MMU: Mapping address range [0x%llx:0x%llx) as ",</span><br><span style="color: hsl(120, 100%, 40%);">+        start, start + size);</span><br><span style="color: hsl(120, 100%, 40%);">+  print_tag(BIOS_INFO, tag);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sanity_check(base_addr, temp_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (temp_size)</span><br><span style="color: hsl(120, 100%, 40%);">+             temp_size -= init_xlat_table(base_addr + (size - temp_size),</span><br><span style="color: hsl(120, 100%, 40%);">+                                       temp_size, tag);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * @brief Init MMU for long mode</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param new_page_table   The new area for page tables. Must not overlap with</span><br><span style="color: hsl(120, 100%, 40%);">+ *                         currently installed page tables.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Can be called multiple times, as long as the new page table area does not</span><br><span style="color: hsl(120, 100%, 40%);">+ * overlap with page tables in use.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If paging isn't active, there are no limitations.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void mmu_init(void *new_page_table)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+       assert(pagetable() != new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      car_set_var(page_tables, new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+     car_set_var(next_free_table, new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Initially mark all table slots unused (first PTE == UNUSED_DESC). */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint64_t *table = pagetable();</span><br><span style="color: hsl(120, 100%, 40%);">+        for (; epagetable() - table > 0; table += GRANULE_SIZE/sizeof(*table))</span><br><span style="color: hsl(120, 100%, 40%);">+             table[0] = UNUSED_DESC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printk(BIOS_DEBUG, "MMU: Initialize the root table (L0)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Initialize the root table (L0) to be completely unmapped. */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint64_t *root = setup_new_table(INVALID_DESC, L0_XLAT_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(root == pagetable());</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Func : mmu_enable</span><br><span style="color: hsl(120, 100%, 40%);">+ * Desc : Install page tables, enable PAE and enable long mode.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void mmu_enable(void *new_page_table)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       assert_correct_pagetable_mapping((uintptr_t)new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert_correct_pagetable_mapping((uintptr_t)new_page_table +</span><br><span style="color: hsl(120, 100%, 40%);">+                          (CONFIG_NUM_PAGE_TABLE_PAGES * 4 * KiB) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Load the new page table address */</span><br><span style="color: hsl(120, 100%, 40%);">+ write_cr3((uintptr_t)new_page_table);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       printk(BIOS_INFO, "MMU: Installed new page tables\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    CRx_TYPE cr0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       cr0 = read_cr0();</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!(cr0 & CR0_PG)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Enable paging */</span><br><span style="color: hsl(120, 100%, 40%);">+           cr0 |= CR0_PG;</span><br><span style="color: hsl(120, 100%, 40%);">+                write_cr0(cr0);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h</span><br><span>index 2e0eeb6..4a37663 100644</span><br><span>--- a/src/commonlib/include/commonlib/cbmem_id.h</span><br><span>+++ b/src/commonlib/include/commonlib/cbmem_id.h</span><br><span>@@ -46,6 +46,7 @@</span><br><span> #define CBMEM_ID_NONE          0x00000000</span><br><span> #define CBMEM_ID_PIRQ             0x49525154</span><br><span> #define CBMEM_ID_POWER_STATE      0x50535454</span><br><span style="color: hsl(120, 100%, 40%);">+#define CBMEM_ID_PAGE               0x50414745</span><br><span> #define CBMEM_ID_RAM_OOPS 0x05430095</span><br><span> #define CBMEM_ID_RAMSTAGE 0x9a357a9e</span><br><span> #define CBMEM_ID_RAMSTAGE_CACHE   0x9a3ca54e</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/c/coreboot/+/30119">change 30119</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/c/coreboot/+/30119"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I6e8b46e65925823a84b8ccd647c7d6848aa20992 </div>
<div style="display:none"> Gerrit-Change-Number: 30119 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <siro@das-labor.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>