From 139831c54c6b19cabae1b79584af620dc8678ba0 Mon Sep 17 00:00:00 2001 From: David Karoly Date: Thu, 22 Sep 2022 15:26:59 +0200 Subject: [PATCH] boot/efi/x86_64: log memory map on bootup Change-Id: I94c169d598d771a813b16e31fd892d7cdafcaad8 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5687 Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- .../platform/efi/arch/x86_64/arch_mmu.cpp | 37 +++++++++ .../platform/efi/arch/x86_64/arch_start.cpp | 81 +++++++++++++++---- 2 files changed, 101 insertions(+), 17 deletions(-) diff --git a/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp b/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp index 8be4d554a0..10edb05e21 100644 --- a/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp +++ b/src/system/boot/platform/efi/arch/x86_64/arch_mmu.cpp @@ -22,6 +22,17 @@ #include "efi_platform.h" +//#define TRACE_MMU +#ifdef TRACE_MMU +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) ; +#endif + + +//#define TRACE_MEMORY_MAP + + extern uint64 gLongGDT; extern uint64 gLongGDTR; segment_descriptor gBootGDT[BOOT_GDT_SEGMENT_COUNT]; @@ -145,6 +156,32 @@ arch_mmu_post_efi_setup(size_t memory_map_size, kRuntimeServices->SetVirtualAddressMap(memory_map_size, descriptor_size, descriptor_version, memory_map); +#ifdef TRACE_MEMORY_MAP + dprintf("phys memory ranges:\n"); + for (uint32_t i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { + uint64 start = gKernelArgs.physical_memory_range[i].start; + uint64 size = gKernelArgs.physical_memory_range[i].size; + dprintf(" 0x%08" B_PRIx64 "-0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + start, start + size, size); + } + + dprintf("allocated phys memory ranges:\n"); + for (uint32_t i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { + uint64 start = gKernelArgs.physical_allocated_range[i].start; + uint64 size = gKernelArgs.physical_allocated_range[i].size; + dprintf(" 0x%08" B_PRIx64 "-0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + start, start + size, size); + } + + dprintf("allocated virt memory ranges:\n"); + for (uint32_t i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { + uint64 start = gKernelArgs.virtual_allocated_range[i].start; + uint64 size = gKernelArgs.virtual_allocated_range[i].size; + dprintf(" 0x%08" B_PRIx64 "-0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + start, start + size, size); + } +#endif + // Important. Make sure supervisor threads can fault on read only pages... asm("mov %%rax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); } diff --git a/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp b/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp index 1564ca5baa..a8334fcb0b 100644 --- a/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/x86_64/arch_start.cpp @@ -43,6 +43,46 @@ arch_convert_kernel_args(void) } +static const char* +memory_region_type_str(int type) +{ + switch (type) { + case EfiReservedMemoryType: + return "EfiReservedMemoryType"; + case EfiLoaderCode: + return "EfiLoaderCode"; + case EfiLoaderData: + return "EfiLoaderData"; + case EfiBootServicesCode: + return "EfiBootServicesCode"; + case EfiBootServicesData: + return "EfiBootServicesData"; + case EfiRuntimeServicesCode: + return "EfiRuntimeServicesCode"; + case EfiRuntimeServicesData: + return "EfiRuntimeServicesData"; + case EfiConventionalMemory: + return "EfiConventionalMemory"; + case EfiUnusableMemory: + return "EfiUnusableMemory"; + case EfiACPIReclaimMemory: + return "EfiACPIReclaimMemory"; + case EfiACPIMemoryNVS: + return "EfiACPIMemoryNVS"; + case EfiMemoryMappedIO: + return "EfiMemoryMappedIO"; + case EfiMemoryMappedIOPortSpace: + return "EfiMemoryMappedIOPortSpace"; + case EfiPalCode: + return "EfiPalCode"; + case EfiPersistentMemory: + return "EfiPersistentMemory"; + default: + return "unknown"; + } +} + + void arch_start_kernel(addr_t kernelEntry) { @@ -51,7 +91,6 @@ arch_start_kernel(addr_t kernelEntry) // First call is to determine the buffer size. size_t memory_map_size = 0; efi_memory_descriptor dummy; - efi_memory_descriptor *memory_map; size_t map_key; size_t descriptor_size; uint32_t descriptor_version; @@ -63,7 +102,7 @@ arch_start_kernel(addr_t kernelEntry) // Allocate a buffer twice as large as needed just in case it gets bigger // between calls to ExitBootServices. size_t actual_memory_map_size = memory_map_size * 2; - memory_map + efi_memory_descriptor *memory_map = (efi_memory_descriptor *)kernel_args_malloc(actual_memory_map_size); if (memory_map == NULL) @@ -78,18 +117,21 @@ arch_start_kernel(addr_t kernelEntry) addr_t addr = (addr_t)memory_map; dprintf("System provided memory map:\n"); - for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) { + for (size_t i = 0; i < memory_map_size / descriptor_size; i++) { efi_memory_descriptor *entry = (efi_memory_descriptor *)(addr + i * descriptor_size); - dprintf(" %#lx-%#lx %#lx %#x %#lx\n", entry->PhysicalStart, + dprintf(" phys: 0x%08lx-0x%08lx, virt: 0x%08lx-0x%08lx, type: %s (%#x), attr: %#lx\n", + entry->PhysicalStart, entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE, - entry->VirtualStart, entry->Type, entry->Attribute); + entry->VirtualStart, + entry->VirtualStart + entry->NumberOfPages * B_PAGE_SIZE, + memory_region_type_str(entry->Type), entry->Type, + entry->Attribute); } // Generate page tables for use after ExitBootServices. uint64_t final_pml4 = arch_mmu_generate_post_efi_page_tables( memory_map_size, memory_map, descriptor_size, descriptor_version); - dprintf("Final PML4 at %#lx\n", final_pml4); // Attempt to fetch the memory map and exit boot services. // This needs to be done in a loop, as ExitBootServices can change the @@ -104,30 +146,35 @@ arch_start_kernel(addr_t kernelEntry) dprintf("Calling ExitBootServices. So long, EFI!\n"); while (true) { if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { - // The console was provided by boot services, disable it. - stdout = NULL; - stderr = NULL; - // Also switch to legacy serial output - // (may not work on all systems) - serial_switch_to_legacy(); - dprintf("Switched to legacy serial output\n"); - break; + // The console was provided by boot services, disable it. + stdout = NULL; + stderr = NULL; + // Also switch to legacy serial output + // (may not work on all systems) + serial_switch_to_legacy(); + dprintf("Switched to legacy serial output\n"); + break; } memory_map_size = actual_memory_map_size; if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) != EFI_SUCCESS) { - panic("Unable to fetch system memory map."); + panic("Unable to fetch system memory map."); } } // Update EFI, generate final kernel physical memory map, etc. arch_mmu_post_efi_setup(memory_map_size, memory_map, - descriptor_size, descriptor_version); + descriptor_size, descriptor_version); smp_boot_other_cpus(final_pml4, kernelEntry, (addr_t)&gKernelArgs); // Enter the kernel! + dprintf("arch_enter_kernel(final_pml4: 0x%08" PRIx64 ", kernelArgs: %p, " + "kernelEntry: 0x%08" B_PRIxADDR ", sp: 0x%08" B_PRIx64 ")\n", + final_pml4, &gKernelArgs, kernelEntry, + gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); + arch_enter_kernel(final_pml4, kernelEntry, - gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); + gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); }