|
| 1 | +## Multi-Architecture Platform Memory Expansion Configuration Guide |
| 2 | + |
| 3 | +This document provides a detailed explanation of how to expand system memory across multiple CPU architecture platforms by modifying configuration files, including RISC-V, AArch64, LoongArch, and x86_64 architectures. |
| 4 | + |
| 5 | +## General Instructions |
| 6 | + |
| 7 | +Before modifying configurations on any platform, please note the following: |
| 8 | + |
| 9 | +- All memory size parameters must be specified in hexadecimal format. |
| 10 | +- The system must be rebuilt after any configuration changes. |
| 11 | +- Memory parameters must be included in the run command. |
| 12 | +- Large memory support requires the `page-alloc-4g` feature. |
| 13 | + |
| 14 | +1. ### RISC-V 64-bit Architecture Configuration |
| 15 | + |
| 16 | + - #### Configuration File Modification |
| 17 | + |
| 18 | + **Path:** `configs/platforms/riscv64-qemu-virt.toml` |
| 19 | + |
| 20 | + ``` |
| 21 | + # Physical Memory Total Size Configuration (4GB) |
| 22 | + # Format: Hexadecimal; underscores are used only for readability |
| 23 | + phys-memory-size = 0x1_0000_0000 # uint type, represents 4GB of physical memory |
| 24 | + ``` |
| 25 | +
|
| 26 | + - #### Build and Run Commands |
| 27 | +
|
| 28 | + ``` |
| 29 | + # Build and run a RISC-V system with 4GB memory |
| 30 | + # Parameter explanation: |
| 31 | + # ARCH=riscv64 - Specifies the architecture |
| 32 | + # PLATFORM=riscv64-qemu-virt - Specifies the platform |
| 33 | + # MEM=4G - Allocates 4GB memory to the QEMU emulator |
| 34 | + # LOG=debug - Enables debug logging |
| 35 | + # AX_TESTCASE=libc - Includes libc test cases |
| 36 | + # BLK=y - Enables block device support |
| 37 | + # NET=y - Enables network support |
| 38 | + # FEATURES=fp_simd,page-alloc-4g - Enables floating-point SIMD and large-page memory allocation |
| 39 | + # ACCEL=n - Disables accelerator |
| 40 | + |
| 41 | + make ARCH=riscv64 PLATFORM=riscv64-qemu-virt MEM=4G LOG=debug AX_TESTCASE=libc BLK=y NET=y FEATURES=fp_simd,page-alloc-4g ACCEL=n run |
| 42 | + ``` |
| 43 | +
|
| 44 | +2. ### AArch64 Architecture Configuration |
| 45 | +
|
| 46 | + - #### Configuration File Modification |
| 47 | +
|
| 48 | + **Path:** `configs/platforms/aarch64-qemu-virt.toml` |
| 49 | +
|
| 50 | + ``` |
| 51 | + # Physical memory total size configuration (4GB) |
| 52 | + # Note: The AArch64 platform usually requires memory regions to be aligned |
| 53 | + phys-memory-size = 0x1_0000_0000 # uint type, represents 4GB of physical memory |
| 54 | + ``` |
| 55 | +
|
| 56 | + - #### Build and Run Command |
| 57 | +
|
| 58 | + ``` |
| 59 | + # Build and run an AArch64 system with 4GB memory |
| 60 | + # The parameters are similar to RISC-V, but targeted for the AArch64 architecture |
| 61 | + make ARCH=aarch64 PLATFORM=aarch64-qemu-virt MEM=4G LOG=debug AX_TESTCASE=libc BLK=y NET=y FEATURES=fp_simd,page-alloc-4g ACCEL=n run |
| 62 | + ``` |
| 63 | +
|
| 64 | +3. ### LoongArch 64-bit Architecture Configuration |
| 65 | +
|
| 66 | + - #### Configuration File Modification |
| 67 | +
|
| 68 | + **Path:** `configs/platforms/loongarch64-qemu-virt.toml` |
| 69 | +
|
| 70 | + ``` |
| 71 | + # Physical memory base address (starts from 0) |
| 72 | + phys-memory-base = 0x0000_0000 # uint type, memory start address |
| 73 | + |
| 74 | + # Total physical memory size (4GB) |
| 75 | + phys-memory-size = 0x1_0000_0000 # uint type, 4GB of memory |
| 76 | + |
| 77 | + # Kernel image physical base address |
| 78 | + # Note: Must be consistent with the page table configuration in boot.rs |
| 79 | + kernel-base-paddr = 0x8020_0000 # uint type, kernel load address |
| 80 | + |
| 81 | + # Kernel image virtual base address |
| 82 | + # LoongArch maps the kernel into high virtual address space |
| 83 | + kernel-base-vaddr = "0xffff_0000_8020_0000" # string type, kernel virtual address |
| 84 | + ``` |
| 85 | +
|
| 86 | + - #### Boot Page Table Modification |
| 87 | +
|
| 88 | + **Path:** `modules/axhal/src/platform/loongarch64_qemu_virt/boot.rs` |
| 89 | +
|
| 90 | + ```rust |
| 91 | + /// Initialize boot page table |
| 92 | + /// Note: Page table entries here must match the memory configuration |
| 93 | + unsafe fn init_boot_page_table() { |
| 94 | + unsafe { |
| 95 | + let l1_va = va!(&raw const BOOT_PT_L1 as usize); |
| 96 | + |
| 97 | + // First-level page table entry configuration: |
| 98 | + // 0x0000_0000_0000 ~ 0x0080_0000_0000, use table mapping |
| 99 | + BOOT_PT_L0[0] = LA64PTE::new_table(crate::mem::virt_to_phys(l1_va)); |
| 100 | + |
| 101 | + // Second-level page table entry configuration: |
| 102 | + // 0x0000_0000..0x4000_0000, 1GB large page, device memory attributes |
| 103 | + BOOT_PT_L1[0] = LA64PTE::new_page( |
| 104 | + pa!(0), |
| 105 | + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, |
| 106 | + true, // large page flag |
| 107 | + ); |
| 108 | + |
| 109 | + // 0x8000_0000..0xc000_0000, 1GB large page, kernel memory attributes |
| 110 | + // Note: Address must match the kernel-base-paddr configuration |
| 111 | + BOOT_PT_L1[2] = LA64PTE::new_page( |
| 112 | + pa!(0x8020_0000), // Modify to actual kernel load address |
| 113 | + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE, |
| 114 | + true, // large page flag |
| 115 | + ); |
| 116 | + } |
| 117 | + } |
| 118 | + ``` |
| 119 | +
|
| 120 | + - #### QEMU Memory Setting |
| 121 | +
|
| 122 | + **Path:** `scripts/make/qemu.mk` |
| 123 | +
|
| 124 | + ``` |
| 125 | + # Default memory size set to 4GB |
| 126 | + override MEM := 4G |
| 127 | + ``` |
| 128 | +
|
| 129 | + - #### Build and Run Command |
| 130 | +
|
| 131 | + ``` |
| 132 | + # Build and run a LoongArch system with 4GB memory |
| 133 | + make ARCH=loongarch64 PLATFORM=loongarch64-qemu-virt MEM=4G LOG=debug AX_TESTCASE=libc BLK=y NET=y FEATURES=fp_simd,page-alloc-4g ACCEL=n run |
| 134 | + ``` |
| 135 | +
|
| 136 | +4. ### x86_64 Architecture Configuration (6GB Memory) |
| 137 | +
|
| 138 | + - #### Configuration File Modification |
| 139 | +
|
| 140 | + **Path:** `configs/platforms/x86_64-qemu-q35.toml` |
| 141 | +
|
| 142 | + ``` |
| 143 | + # Total physical memory size (6GB) |
| 144 | + phys-memory-size = 0x1_8000_0000 # uint type, 6GB memory |
| 145 | + |
| 146 | + # MMIO region configuration, format: (base address, size) |
| 147 | + mmio-regions = [ |
| 148 | + [0xb000_0000, 0x1000_0000], # PCI config space |
| 149 | + [0xfe00_0000, 0xc0_0000], # PCI device region |
| 150 | + [0xfec0_0000, 0x1000], # IO APIC |
| 151 | + [0xfed0_0000, 0x1000], # HPET timer |
| 152 | + [0xfee0_0000, 0x1000], # Local APIC |
| 153 | + [0xc000000000, 0x1000000000], # 64-bit PCI address space (new region) |
| 154 | + ] # [(uint, uint)] |
| 155 | + ``` |
| 156 | +
|
| 157 | + - #### Memory Management Module Modification |
| 158 | +
|
| 159 | + **Path:** `modules/axhal/src/mem.rs` |
| 160 | +
|
| 161 | + ```rust |
| 162 | + /// Get the default free memory region |
| 163 | + /// Returns available memory from the end of the kernel to the start of MMIO or end of physical memory |
| 164 | + pub(crate) fn default_free_regions() -> impl Iterator<Item = MemRegion> { |
| 165 | + let start = virt_to_phys((_ekernel as usize).into()).align_up_4k(); // First 4K-aligned address after kernel |
| 166 | + let mmio_start = pa!(0xb0000000); // MMIO start address |
| 167 | + let phys_end = pa!(PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE).align_down_4k(); // End of physical memory |
| 168 | + |
| 169 | + let end = core::cmp::min(mmio_start, phys_end); // Use the smaller of MMIO start or physical end |
| 170 | + |
| 171 | + core::iter::once(MemRegion { |
| 172 | + paddr: start, |
| 173 | + size: end.as_usize() - start.as_usize(), |
| 174 | + flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE, |
| 175 | + name: "free memory", |
| 176 | + }) |
| 177 | + } |
| 178 | + ``` |
| 179 | +
|
| 180 | + **Path:** `modules/axhal/src/platform/x86_pc/mem.rs` |
| 181 | +
|
| 182 | + ```rust |
| 183 | + /// Returns platform-specific memory region configuration |
| 184 | + pub(crate) fn platform_regions() -> impl Iterator<Item = MemRegion> { |
| 185 | + core::iter::once(MemRegion { |
| 186 | + paddr: pa!(0x1000), // Skip first page |
| 187 | + size: 0x9e000, // Traditional low memory size |
| 188 | + flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, |
| 189 | + name: "low memory", |
| 190 | + }) |
| 191 | + .chain(crate::mem::default_free_regions()) // Default free memory region |
| 192 | + .chain(crate::mem::default_mmio_regions()) // Default MMIO region |
| 193 | + .chain(core::iter::once(MemRegion { // Extended memory region (6GB config addition) |
| 194 | + paddr: pa!(0x100000000), // Starts at 4GB |
| 195 | + size: 0x80000000, // Extends to 6GB (0x180000000) |
| 196 | + flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE, |
| 197 | + name: "extended memory 3", |
| 198 | + })) |
| 199 | + } |
| 200 | + ``` |
| 201 | +
|
| 202 | + - #### Boot Page Table Modification |
| 203 | +
|
| 204 | + **Path:** `modules/axhal/src/platform/x86_pc/multiboot.S` |
| 205 | +
|
| 206 | + ``` |
| 207 | + /* Lower half Page Directory Pointer Table */ |
| 208 | + .Ltmp_pdpt_low: |
| 209 | + .quad 0x0000 | 0x83 # 0–1GB: PRESENT | WRITABLE | HUGE_PAGE |
| 210 | + .quad 0x40000000 | 0x83 # 1–2GB |
| 211 | + .quad 0x80000000 | 0x83 # 2–3GB |
| 212 | + .quad 0xc0000000 | 0x83 # 3–4GB |
| 213 | + .quad 0x100000000 | 0x83 # 4–5GB (new) |
| 214 | + .quad 0x140000000 | 0x83 # 5–6GB (new) |
| 215 | + .zero 8 * 506 # Zero the remaining entries |
| 216 | + |
| 217 | + /* Upper half Page Directory Pointer Table (mirrored layout) */ |
| 218 | + .Ltmp_pdpt_high: |
| 219 | + .quad 0x0000 | 0x83 # 0–1GB |
| 220 | + .quad 0x40000000 | 0x83 # 1–2GB |
| 221 | + .quad 0x80000000 | 0x83 # 2–3GB |
| 222 | + .quad 0xc0000000 | 0x83 # 3–4GB |
| 223 | + .quad 0x100000000 | 0x83 # 4–5GB (new) |
| 224 | + .quad 0x140000000 | 0x83 # 5–6GB (new) |
| 225 | + .zero 8 * 506 # Zero the remaining entries |
| 226 | + ``` |
| 227 | +
|
| 228 | + - #### Build and Run Command |
| 229 | +
|
| 230 | + ``` |
| 231 | + # Build and run an x86_64 system with 6GB memory |
| 232 | + make ARCH=x86_64 PLATFORM=x86_64-qemu-q35 MEM=6G LOG=debug AX_TESTCASE=libc BLK=y NET=y FEATURES=fp_simd,page-alloc-4g ACCEL=n run |
| 233 | + ``` |
| 234 | +
|
| 235 | +## Notes |
| 236 | +
|
| 237 | +- A full system rebuild is required after modifying memory configuration. |
| 238 | +- Memory mapping differs significantly across architectures. |
| 239 | +- Large memory configurations require support from all related components (e.g., page tables, memory allocators). |
| 240 | +- It's recommended to increase memory size incrementally and test system stability. |
| 241 | +- Some architectures may require additional kernel or QEMU parameters to support large memory sizes. |
| 242 | +
|
| 243 | +
|
| 244 | +
|
| 245 | +
|
| 246 | +
|
0 commit comments