Opened 10 years ago
Last modified 9 years ago
#11896 closed bug
ARM loader: arch_mmu positioning dynamic va start incorrectly. — at Version 12
Reported by: | kallisti5 | Owned by: | pdziepak |
---|---|---|---|
Priority: | normal | Milestone: | Unscheduled |
Component: | System/Boot Loader | Version: | R1/Development |
Keywords: | ARM MMU pfoetchen mmu_man rpi2 | Cc: | |
Blocked By: | Blocking: | ||
Platform: | arm |
Description (last modified by )
src/system/boot/arch/arm/arch_mmu.cpp
// Mark start for dynamic allocation IsNextPhysicalAddress = IsNextVirtualAddress = sPageTableRegionEnd;
(per mmu_man)
src/system/boot/arch/arm/arch_mmu.cpp: sPageTableRegionEnd = (addr_t)sPageDirectory + 0x200000; src/system/boot/arch/arm/arch_mmu.cpp: sPageDirectory = (uint32 *)ROUNDUP((addr_t)&_end, 0x100000); src/system/boot/arch/arm/arch_mmu.cpp:extern int _start, _end; ./src/system/ldscripts/arm/boot_loader_u-boot.ld . = BOARD_LOADER_BASE; . . _end = . ;
Example boot on Raspberry Pi 2..
reading /boot.scr 312 bytes read in 15 ms (19.5 KiB/s) ## Executing script at 00000000 reading bcm2836-rpi-2-b.dtb 5690 bytes read in 16 ms (346.7 KiB/s) reading haiku-floppyboot.tgz.ub 1596766 bytes read in 600 ms (2.5 MiB/s) reading haiku_loader_linux.ub 288696 bytes read in 124 ms (2.2 MiB/s) ## Booting kernel from Legacy Image at 01000000 ... Image Name: haiku_loader rpi2 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 288632 Bytes = 281.9 KiB Load Address: 00080000 Entry Point: 00080010 Verifying Checksum ... OK ## Loading init Ramdisk from Legacy Image at 02100000 ... Image Name: haiku-floppyboot.tgz rpi2 Image Type: ARM Linux RAMDisk Image (uncompressed) Data Size: 1596702 Bytes = 1.5 MiB Load Address: 00000000 Entry Point: 00000000 Verifying Checksum ... OK ## Flattened Device Tree blob at 02000000 Booting using the fdt blob at 0x2000000 Loading Kernel Image ... OK Loading Ramdisk to 079c4000, end 07b49d1e ... OK Loading Device Tree to 079bf000, end 079c3639 ... OK Starting kernel ... �check_cpu_features: implementor=0x41('A'), arch=9, variant=0x0, part=0xc07, revision=0x5 Found boot tgz from FDT @ 0x079c4000, 1596702 bytes argc = 0 os: 2 gd @ 0x00000000 FDT @ 0x079bf000: fdt_totalsize: 8320 fdt_off_dt_struct: 88 fdt_off_dt_strings: 5252 fdt_off_mem_rsvmap: 40 fdt_version: 17 fdt_last_comp_version: 16 fdt_boot_cpuid_phys: 0 fdt_size_dt_strings: 733 fdt_size_dt_struct: 5164 checking for memory... 0: base = 0,size = 134217728 total physical memory = 128MB *** PANIC *** *** PANIC *** map_page: asked to map invalid page 0x00300000! map_page: asked to map invalid page 0x00300000! Press key to reboot. *** PANIC *** *** PANIC *** map_page: asked to map invalid page 0x00301000! map_page: asked to map invalid page 0x00301000! Press key to reboot. *** PANIC *** *** PANIC *** map_page: asked to map invalid page 0x00302000! map_page: asked to map invalid page 0x00302000! Press key to reboot. . .
Change History (14)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
The 0x00300000 it is attempting to map seems to be the physical address for the MMC card. (http://cgit.haiku-os.org/haiku/tree/headers/private/kernel/arch/arm/bcm283X.h#n80)
I'm guessing u-boot handed the MMC pointer off? One odd thing is that address should be 0x3f300000 as it is BCM283X_PERIPHERAL_BASE + EMMC_BASE.
I wonder if that's a u-boot bug?
comment:3 by , 10 years ago
Have you enabled TRACE in the mmu files? It should log more info about what it does, which would help finding the problem.
comment:5 by , 10 years ago
75 mmu_map_identity: [ 100000 - 300000] 76 get_next_page_table, sNextPageTableAddress 0x104400, sPageTableRegionEnd 0x300000, type 0x1 77 get_next_page_table, sNextPageTableAddress 0x104800, sPageTableRegionEnd 0x300000, type 0x1
Then a bit later:
107 map_page: vaddr 0x300000, paddr 0x300000 108 *** PANIC ***
So it would seem the initial identity mapping for that area is not big enough, and we try to access something at address 0x300000 which was not properly mapped?
comment:6 by , 10 years ago
Ah. I missed that fact :-)
kallisti5@eris haiku :) $ grep -RnA1 "mmu_map_identity" src/ system/boot/arch/arm/arch_mmu.cpp:284:mmu_map_identity(addr_t start, size_t end, int flags) -- system/boot/arch/arm/arch_mmu.cpp:292:TRACE(("mmu_map_identity: [ %" B_PRIxADDR " - %" B_PRIxADDR "]\n", start, end)); -- system/boot/arch/arm/arch_mmu.cpp:320:mmu_map_identity((addr_t)&_start, (addr_t)&_end, ARM_MMU_L2_FLAG_C); -- system/boot/arch/arm/arch_mmu.cpp:323:mmu_map_identity((addr_t)sPageDirectory, sPageTableRegionEnd, ARM_MMU_L2_FLAG_C); -- system/boot/arch/arm/arch_mmu.cpp:333:mmu_map_identity(LOADER_MEMORYMAP[i].start, LOADER_MEMORYMAP[i].end, system/boot/arch/arm/arch_mmu.cpp-334- LOADER_MEMORYMAP[i].flags);
comment:7 by , 10 years ago
Looking at the logs and the mmu code,
src/system/boot/arch/arm/arch_mmu.cpp init_page_directory()... // **** // 80000 - d0000 here.... // ***** // map ourselfs first... just to make sure mmu_map_identity((addr_t)&_start, (addr_t)&_end, ARM_MMU_L2_FLAG_C); // **** // 100000 - 300000 here.... // ***** // map our page directory region (TODO should not be identity mapped) mmu_map_identity((addr_t)sPageDirectory, sPageTableRegionEnd, ARM_MMU_L2_FLAG_C);
So what is attempting to use the 300000+?
comment:8 by , 10 years ago
Actually, looking at mmu_man's comments... this makes sense.
dynamic allocation is at the PageTableRegionEnd...
// allocate page directory in memory after loader sPageDirectory = (uint32 *)ROUNDUP((addr_t)&_end, 0x100000); sNextPageTableAddress = (addr_t)sPageDirectory + ARM_MMU_L1_TABLE_SIZE; sPageTableRegionEnd = (addr_t)sPageDirectory + 0x200000; // Mark start for dynamic allocation sNextPhysicalAddress = sNextVirtualAddress = sPageTableRegionEnd;
So:
- loader 80000 - d0000
- insert_physical_allocated_range
- pageDirectory 100000 - 300000
- insert_physical_allocated_range
- dynamicAllocation 300000+
- init_page_directory();
- mmu_map_identity loader 80000 - d0000
- mmu_map_identity pageDirectory 100000 - 300000
This all means the first map_page request for a dynamic range coming in fails..
mmu_allocate: requested vaddr: 0x00000000, next free vaddr: 0x300000, size: 16384 map_page: vaddr 0x300000, paddr 0x300000 *** PANIC *** *** PANIC *** map_page: asked to map invalid page 0x00300000! map_page: asked to map invalid page 0x00300000!
mmu_allocate says the first virtual memory for the dynamic range is 0x300000... is that right?
static void map_page(addr_t virtualAddress, addr_t physicalAddress, uint32 flags) { TRACE(("map_page: vaddr 0x%lx, paddr 0x%lx\n", virtualAddress, physicalAddress)); if (virtualAddress < KERNEL_LOAD_BASE) { panic("map_page: asked to map invalid page %p!\n", (void *)virtualAddress); }
headers/private/kernel/arch/arm/arch_kernel.h:#define KERNEL_BASE 0x80000000
so.... there is the issue. We're setting vaddr to start at 0x300000, but the mmu_page checks for >= KERNEL_BASE (0x80000000)
by , 10 years ago
Attachment: | 0001-loader-arm-mmu-Set-first-available-va-to-KERNEL_LOAD.patch added |
---|
patch. I need to test this evening.
comment:10 by , 10 years ago
patch: | 0 → 1 |
---|
comment:11 by , 10 years ago
... although maybe sNextVirtualAddress should be KERNEL_LOAD_BASE + kMaxKernelSize?
comment:12 by , 10 years ago
Description: | modified (diff) |
---|---|
Summary: | ARM: arch_mmu assumes RAM starts at 80000000 → ARM loader: arch_mmu positioning dynamic va start incorrectly. |
I'm not sure about that, the mmu code was written to work with several different mappings and the beagleboard was the first time we had RAM at this address, which was a problem because the mmu code wouldn't handle it too well.
Some details about the MMU mapping process:
So the 80000000 you are seeing is setup from the boot loader, and is not related to the RAM physical address in any way.