Simon Glass | 67aadc1 | 2024-09-26 14:28:51 +0200 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | |
| 3 | Memory Management |
Neha Malcom Francis | 5a56051 | 2025-03-19 19:33:27 +0530 | [diff] [blame] | 4 | ================= |
Simon Glass | 67aadc1 | 2024-09-26 14:28:51 +0200 | [diff] [blame] | 5 | |
| 6 | .. note:: |
| 7 | |
| 8 | This information is outdated and needs to be updated. |
| 9 | |
| 10 | U-Boot runs in system state and uses physical addresses, i.e. the |
| 11 | MMU is not used either for address mapping nor for memory protection. |
| 12 | |
| 13 | The available memory is mapped to fixed addresses using the |
| 14 | memory-controller. In this process, a contiguous block is formed for each |
| 15 | memory type (Flash, SDRAM, SRAM), even when it consists of several |
| 16 | physical-memory banks. |
| 17 | |
| 18 | U-Boot is installed in XIP flash memory, or may be loaded into a lower region of |
| 19 | RAM by a secondary program loader (SPL). After |
| 20 | booting and sizing and initialising DRAM, the code relocates itself |
| 21 | to the upper end of DRAM. Immediately below the U-Boot code some |
| 22 | memory is reserved for use by malloc() [see CONFIG_SYS_MALLOC_LEN |
| 23 | configuration setting]. Below that, a structure with global Board-Info |
| 24 | data is placed, followed by the stack (growing downward). |
| 25 | |
| 26 | Additionally, some exception handler code may be copied to the low 8 kB |
| 27 | of DRAM (0x00000000 ... 0x00001fff). |
| 28 | |
| 29 | So a typical memory configuration with 16 MB of DRAM could look like |
| 30 | this:: |
| 31 | |
| 32 | 0x0000 0000 Exception Vector code |
| 33 | : |
| 34 | 0x0000 1fff |
| 35 | 0x0000 2000 Free for Application Use |
| 36 | : |
| 37 | : |
| 38 | |
| 39 | : |
| 40 | : |
| 41 | 0x00fb ff20 Monitor Stack (Growing downward) |
| 42 | 0x00fb ffac Board Info Data and permanent copy of global data |
| 43 | 0x00fc 0000 Malloc Arena |
| 44 | : |
| 45 | 0x00fd ffff |
| 46 | 0x00fe 0000 RAM Copy of Monitor Code |
| 47 | ... eventually: LCD or video framebuffer |
| 48 | ... eventually: pRAM (Protected RAM - unchanged by reset) |
| 49 | 0x00ff ffff [End of RAM] |
Neha Malcom Francis | 5a56051 | 2025-03-19 19:33:27 +0530 | [diff] [blame] | 50 | |
| 51 | System RAM Utilization in U-Boot in ARM |
| 52 | --------------------------------------- |
| 53 | |
| 54 | Let us break down the relevant parts of the execution sequence where system RAM |
| 55 | comes into play. Please note that these are individual pieces of the entire |
| 56 | boot sequence. It is not exhaustive, rather it aims to show only the pieces |
| 57 | where the system RAM is modified. See arch/arm/lib/crt0* to understand the |
| 58 | complete execution sequence. |
| 59 | |
| 60 | Also note that the below sequence is not a hard and fast rule on how DRAM usage |
| 61 | would be and an architecture and board specific analysis is required for the |
| 62 | exact flow. |
| 63 | |
| 64 | SPL Flow |
| 65 | ........ |
| 66 | |
| 67 | #. Pre-DRAM |
| 68 | |
| 69 | Prior to setting up of the DRAM, the stack, malloc is defined as below |
| 70 | possibly sitting on a smaller readily available memory (SRAM etc.): |
| 71 | |
| 72 | .. image:: pics/spl_before_reloc.svg |
| 73 | :alt: contents of ready RAM before relocation in SPL |
| 74 | |
| 75 | Please see CONFIG_SPL_EARLY_BSS if BSS initialization is needed prior |
| 76 | to entering board_init_f(). |
| 77 | |
| 78 | |
| 79 | #. DRAM Initialization |
| 80 | |
| 81 | This is typically triggered by board_init_f prior to relocating the stack |
| 82 | and the GD (optionally) to the system RAM. DRAM drivers reside in |
| 83 | drivers/ram/. Their probe/configuration can be done either via placing the |
| 84 | logic in dram_init() or wherever deemed applicable within board_init_f. |
| 85 | |
| 86 | Post board_init_f, spl_relocate_stack_gd() is called to relocate the stack |
| 87 | and the GD to the newly initialized DRAM. If CONFIG_SPL_SYS_MALLOC_SIMPLE |
| 88 | is set it is also possible to use some amount of this DRAM stack as memory |
| 89 | pool for malloc_simple. |
| 90 | |
| 91 | Both of which are an optional move at this point in the sequence. This is |
| 92 | still an intermediate environment. |
| 93 | |
| 94 | #. Final Environment Set Up |
| 95 | |
| 96 | The final environment is setup and the system RAM now looks like this: |
| 97 | |
| 98 | .. image:: pics/spl_after_reloc.svg |
| 99 | :alt: contents of DRAM after relocation in SPL |
| 100 | |
| 101 | Again stack and gd are an optional move and may still remain in the |
| 102 | available RAM (SRAM, locked cache etc.) |
| 103 | |
| 104 | U-Boot Proper Flow |
| 105 | .................. |
| 106 | |
| 107 | TODO: this section is still under progress |
| 108 | |
| 109 | #. DRAM Initialization |
| 110 | |
| 111 | This follows the same as in SPL flow. In board_init_f(), a part of memory |
| 112 | is reserved at the end of RAM (see reserve_* functions in init_sequence_f) |
| 113 | |
| 114 | #. Code Relocation |
| 115 | |
| 116 | relocate_code() is called which relocates U-Boot code from the current |
| 117 | location into the relocation destination in system RAM. Typically it is |
| 118 | relocated to the upper portion of the memory. So DRAM now has: |
| 119 | * stack |
| 120 | * gd |
| 121 | * code |
| 122 | |
| 123 | The code relocation happens to the upper portion of the memory after certain |
| 124 | portion of memory is reserved. This is memory that is intended to not be |
| 125 | "touched" by U-Boot. |
| 126 | |
| 127 | #. Final Environment Set Up |
| 128 | |
| 129 | At this stage we are completely running out of the system RAM with: |
| 130 | * stack |
| 131 | * gd |
| 132 | * code |
| 133 | * bss |
| 134 | * initialized non-const data |
| 135 | * initialized const data |
| 136 | |
| 137 | It is better to do a complete analysis to visualize the layers the system |
| 138 | RAM is composed of at the end of this flow. This is entirely dependent on |
| 139 | CPU/SoC architecture. |
| 140 | |
| 141 | Getting information about system RAM |
| 142 | .................................... |
| 143 | |
| 144 | At boot: |
| 145 | |
| 146 | The prints given by announce_dram_init() and show_dram_config() come up in the |
| 147 | boot banner like so:: |
| 148 | |
| 149 | DRAM: 2 GiB (total 32 GiB) |
| 150 | |
| 151 | U-Boot supports addressing upto 39-bit. To avoid trying to access higher |
| 152 | addresses in systems with > 39-bit addresses, U-Boot caps itself (gd->ram_size) |
| 153 | to the first bank. This is also inline with philosophy that U-Boot is a |
| 154 | bootloader and not a full-fledged operating system. The first value represents |
| 155 | this memory that is available for U-Boot while the "total" value represents the |
| 156 | total system RAM available on the device. |
| 157 | |
| 158 | Getting the most basic information on how system RAM has been set up is by |
| 159 | running `bdinfo` at U-Boot prompt:: |
| 160 | |
| 161 | => bdinfo |
| 162 | boot_params = 0x0000000000000000 |
| 163 | DRAM bank = 0x0000000000000000 |
| 164 | -> start = 0x0000000080000000 |
| 165 | -> size = 0x0000000080000000 |
| 166 | DRAM bank = 0x0000000000000001 |
| 167 | -> start = 0x0000000880000000 |
| 168 | -> size = 0x0000000780000000 |
| 169 | flashstart = 0x0000000000000000 |
| 170 | flashsize = 0x0000000000000000 |
| 171 | flashoffset = 0x0000000000000000 |
| 172 | baudrate = 115200 bps |
| 173 | relocaddr = 0x00000000ffec1000 |
| 174 | reloc off = 0x000000007f6c1000 |
| 175 | Build = 64-bit |
| 176 | current eth = ethernet@46000000port@1 |
| 177 | ethaddr = 3c:e0:64:62:4b:4e |
| 178 | IP addr = <NULL> |
| 179 | fdt_blob = 0x00000000fde7df60 |
| 180 | lmb_dump_all: |
| 181 | memory.count = 0x1 |
| 182 | memory[0] [0x80000000-0xffffffff], 0x80000000 bytes flags: none |
| 183 | reserved.count = 0x2 |
| 184 | reserved[0] [0x9e800000-0xabffffff], 0x0d800000 bytes flags: no-map |
| 185 | reserved[1] [0xfce79f50-0xffffffff], 0x031860b0 bytes flags: no-overwrite |
| 186 | devicetree = separate |
| 187 | serial addr = 0x0000000002880000 |
| 188 | width = 0x0000000000000000 |
| 189 | shift = 0x0000000000000002 |
| 190 | offset = 0x0000000000000000 |
| 191 | clock = 0x0000000002dc6c00 |
| 192 | arch_number = 0x0000000000000000 |
| 193 | TLB addr = 0x00000000ffff0000 |
| 194 | irq_sp = 0x00000000fde7df50 |
| 195 | sp start = 0x00000000fde7df50 |
| 196 | Early malloc usage: 3288 / 8000 |
| 197 | |
| 198 | |
| 199 | Here you are able to see the banks of DDR that have been set up in DRAM bank |
| 200 | -> start and -> size as well as the reserved memories in lmb_dump_all. |
| 201 | |
| 202 | Testing Memory |
| 203 | -------------- |
| 204 | |
| 205 | Please see doc/README.memory-test |