boot/efi: factor out generic mmu functions
This change moves the common functions related to EFI memory map to arch/generic for arm, arm64, x86. riscv64 and x86_64 shall be handled separately as they use some more architecture-specific logic: * riscv64 needs special treatment for the M-mode resident code located at 0x80000000 which is reported as available in the EFI memory map provided by u-boot. * x86_64 has a slightly different logic for building the memory regions list so some additional rework and testing will be needed before it can be unified with the generic mmu functions. Change-Id: I430c84dfc693c5b6f04c170dec8ffb1db2c2ace1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5694 Reviewed-by: waddlesplash <waddlesplash@gmail.com> Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
parent
c907db6c62
commit
a3c9f71efd
@ -1,6 +1,7 @@
|
||||
SubDir HAIKU_TOP src system boot platform efi arch arm ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) $(DOTDOT) ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||
|
||||
UseLibraryHeaders [ FDirName libfdt ] ;
|
||||
|
||||
@ -11,29 +12,37 @@ UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||
|
||||
local platform ;
|
||||
for platform in [ MultiBootSubDirSetup efi ] {
|
||||
on $(platform) {
|
||||
{
|
||||
local defines = _BOOT_MODE _BOOT_PLATFORM_EFI ;
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) ;
|
||||
SubDirC++Flags $(defines) -fno-rtti ;
|
||||
}
|
||||
on $(platform) {
|
||||
{
|
||||
local defines = _BOOT_MODE _BOOT_PLATFORM_EFI ;
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) ;
|
||||
SubDirC++Flags $(defines) -fno-rtti ;
|
||||
}
|
||||
|
||||
local arch_src =
|
||||
crt0-efi-$(TARGET_ARCH).S
|
||||
entry.S
|
||||
cache.S
|
||||
relocation_func.cpp
|
||||
arch_cpu.cpp
|
||||
arch_dtb.cpp
|
||||
arch_mmu.cpp
|
||||
arch_smp.cpp
|
||||
arch_start.cpp
|
||||
arch_timer.cpp
|
||||
;
|
||||
local arch_src =
|
||||
crt0-efi-$(TARGET_ARCH).S
|
||||
entry.S
|
||||
cache.S
|
||||
relocation_func.cpp
|
||||
arch_cpu.cpp
|
||||
arch_dtb.cpp
|
||||
arch_mmu.cpp
|
||||
arch_smp.cpp
|
||||
arch_start.cpp
|
||||
arch_timer.cpp
|
||||
;
|
||||
|
||||
BootMergeObject boot_platform_efi_arm.o :
|
||||
$(arch_src)
|
||||
;
|
||||
local generic_src =
|
||||
generic_mmu.cpp
|
||||
;
|
||||
|
||||
BootMergeObject boot_platform_efi_arm.o :
|
||||
$(arch_src)
|
||||
$(generic_src)
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles $(generic_src) ]
|
||||
= [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,9 @@
|
||||
#include <efi/types.h>
|
||||
#include <efi/boot-services.h>
|
||||
|
||||
#include "mmu.h"
|
||||
#include "efi_platform.h"
|
||||
#include "generic_mmu.h"
|
||||
#include "mmu.h"
|
||||
|
||||
|
||||
//#define TRACE_MMU
|
||||
@ -29,6 +30,10 @@
|
||||
//#define TRACE_MEMORY_MAP
|
||||
//#define TRACE_PAGE_DIRECTORY
|
||||
|
||||
// Ignore memory above 512GB
|
||||
#define PHYSICAL_MEMORY_LOW 0x00000000
|
||||
#define PHYSICAL_MEMORY_HIGH 0x8000000000ull
|
||||
|
||||
#define ALIGN_PAGEDIR (1024 * 16)
|
||||
#define MAX_PAGE_TABLES 192
|
||||
#define PAGE_TABLE_AREA_SIZE (MAX_PAGE_TABLES * ARM_MMU_L2_COARSE_TABLE_SIZE)
|
||||
@ -160,87 +165,6 @@ map_range_to_new_area(efi_memory_descriptor *entry, uint32_t flags)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_physical_memory_list(size_t memoryMapSize,
|
||||
efi_memory_descriptor *memoryMap, size_t descriptorSize,
|
||||
uint32_t descriptorVersion)
|
||||
{
|
||||
addr_t addr = (addr_t)memoryMap;
|
||||
|
||||
gKernelArgs.num_physical_memory_ranges = 0;
|
||||
|
||||
// First scan: Add all usable ranges
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory: {
|
||||
// Usable memory.
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
insert_physical_memory_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t initialPhysicalMemory = total_physical_memory();
|
||||
|
||||
// Second scan: Remove everything reserved that may overlap
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
break;
|
||||
default:
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
remove_physical_memory_range(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
gKernelArgs.ignored_physical_memory
|
||||
+= initialPhysicalMemory - total_physical_memory();
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_memory_range,
|
||||
gKernelArgs.num_physical_memory_ranges);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_physical_allocated_list(size_t memoryMapSize,
|
||||
efi_memory_descriptor *memoryMap, size_t descriptorSize,
|
||||
uint32_t descriptorVersion)
|
||||
{
|
||||
addr_t addr = (addr_t)memoryMap;
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderData: {
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
insert_physical_allocated_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_allocated_range,
|
||||
gKernelArgs.num_physical_allocated_ranges);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_mmu_post_efi_setup(size_t memoryMapSize,
|
||||
efi_memory_descriptor *memoryMap, size_t descriptorSize,
|
||||
@ -317,7 +241,8 @@ arch_mmu_generate_post_efi_page_tables(size_t memoryMapSize,
|
||||
arch_mmu_allocate_page_tables();
|
||||
|
||||
build_physical_memory_list(memoryMapSize, memoryMap,
|
||||
descriptorSize, descriptorVersion);
|
||||
descriptorSize, descriptorVersion,
|
||||
PHYSICAL_MEMORY_LOW, PHYSICAL_MEMORY_HIGH);
|
||||
|
||||
addr_t memoryMapAddr = (addr_t)memoryMap;
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <boot/stdio.h>
|
||||
|
||||
#include "efi_platform.h"
|
||||
#include "generic_mmu.h"
|
||||
#include "mmu.h"
|
||||
#include "serial.h"
|
||||
#include "smp.h"
|
||||
@ -53,46 +54,6 @@ arch_convert_kernel_args(void)
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
memory_region_type_str(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case EfiReservedMemoryType:
|
||||
return "ReservedMemoryType";
|
||||
case EfiLoaderCode:
|
||||
return "LoaderCode";
|
||||
case EfiLoaderData:
|
||||
return "LoaderData";
|
||||
case EfiBootServicesCode:
|
||||
return "BootServicesCode";
|
||||
case EfiBootServicesData:
|
||||
return "BootServicesData";
|
||||
case EfiRuntimeServicesCode:
|
||||
return "RuntimeServicesCode";
|
||||
case EfiRuntimeServicesData:
|
||||
return "RuntimeServicesData";
|
||||
case EfiConventionalMemory:
|
||||
return "ConventionalMemory";
|
||||
case EfiUnusableMemory:
|
||||
return "UnusableMemory";
|
||||
case EfiACPIReclaimMemory:
|
||||
return "ACPIReclaimMemory";
|
||||
case EfiACPIMemoryNVS:
|
||||
return "ACPIMemoryNVS";
|
||||
case EfiMemoryMappedIO:
|
||||
return "MMIO";
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
return "MMIOPortSpace";
|
||||
case EfiPalCode:
|
||||
return "PalCode";
|
||||
case EfiPersistentMemory:
|
||||
return "PersistentMemory";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
allocate_trampoline_page(void)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
SubDir HAIKU_TOP src system boot platform efi arch arm64 ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) $(DOTDOT) ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||
|
||||
UseLibraryHeaders [ FDirName libfdt ] ;
|
||||
|
||||
@ -9,32 +10,40 @@ UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||
|
||||
local platform ;
|
||||
for platform in [ MultiBootSubDirSetup efi ] {
|
||||
on $(platform) {
|
||||
{
|
||||
local defines = _BOOT_MODE _BOOT_PLATFORM_EFI ;
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) ;
|
||||
SubDirC++Flags $(defines) -fno-rtti ;
|
||||
}
|
||||
on $(platform) {
|
||||
{
|
||||
local defines = _BOOT_MODE _BOOT_PLATFORM_EFI ;
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) ;
|
||||
SubDirC++Flags $(defines) -fno-rtti ;
|
||||
}
|
||||
|
||||
local arch_src =
|
||||
crt0-efi-$(TARGET_ARCH).S
|
||||
entry.S
|
||||
transition.S
|
||||
exceptions.S
|
||||
cache.S
|
||||
relocation_func.cpp
|
||||
arch_acpi.cpp
|
||||
arch_cache.cpp
|
||||
arch_dtb.cpp
|
||||
arch_mmu.cpp
|
||||
arch_smp.cpp
|
||||
arch_start.cpp
|
||||
arch_timer.cpp
|
||||
;
|
||||
local arch_src =
|
||||
crt0-efi-$(TARGET_ARCH).S
|
||||
entry.S
|
||||
transition.S
|
||||
exceptions.S
|
||||
cache.S
|
||||
relocation_func.cpp
|
||||
arch_acpi.cpp
|
||||
arch_cache.cpp
|
||||
arch_dtb.cpp
|
||||
arch_mmu.cpp
|
||||
arch_smp.cpp
|
||||
arch_start.cpp
|
||||
arch_timer.cpp
|
||||
;
|
||||
|
||||
BootMergeObject boot_platform_efi_arm64.o :
|
||||
$(arch_src)
|
||||
;
|
||||
local generic_src =
|
||||
generic_mmu.cpp
|
||||
;
|
||||
|
||||
BootMergeObject boot_platform_efi_arm64.o :
|
||||
$(arch_src)
|
||||
$(generic_src)
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles $(generic_src) ]
|
||||
= [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,9 @@
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
#include "mmu.h"
|
||||
#include "efi_platform.h"
|
||||
#include "generic_mmu.h"
|
||||
#include "mmu.h"
|
||||
|
||||
#include "aarch64.h"
|
||||
#include "arch_mmu.h"
|
||||
@ -23,6 +24,9 @@
|
||||
//#define TRACE_MEMORY_MAP
|
||||
//#define TRACE_PAGE_DIRECTORY
|
||||
|
||||
// Ignore memory above 512GB
|
||||
#define PHYSICAL_MEMORY_LOW 0x00000000
|
||||
#define PHYSICAL_MEMORY_HIGH 0x8000000000ull
|
||||
|
||||
ARMv8TranslationRegime::TranslationDescriptor translation4Kb48bits = {
|
||||
{L0_SHIFT, L0_ADDR_MASK, false, true, false },
|
||||
@ -268,97 +272,6 @@ map_range(addr_t virt_addr, phys_addr_t phys_addr, size_t size, uint64_t flags)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_physical_memory_list(size_t memory_map_size,
|
||||
efi_memory_descriptor* memory_map, size_t descriptor_size,
|
||||
uint32_t descriptor_version)
|
||||
{
|
||||
addr_t addr = (addr_t)memory_map;
|
||||
|
||||
gKernelArgs.num_physical_memory_ranges = 0;
|
||||
|
||||
// First scan: Add all usable ranges
|
||||
for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor*)(addr + i * descriptor_size);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
entry->VirtualStart = entry->PhysicalStart;
|
||||
break;
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory: {
|
||||
// Usable memory.
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
insert_physical_memory_range(base, size);
|
||||
break;
|
||||
}
|
||||
case EfiACPIReclaimMemory:
|
||||
// ACPI reclaim -- physical memory we could actually use later
|
||||
break;
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
entry->VirtualStart = entry->PhysicalStart;
|
||||
break;
|
||||
case EfiMemoryMappedIO:
|
||||
entry->VirtualStart = entry->PhysicalStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t initialPhysicalMemory = total_physical_memory();
|
||||
|
||||
// Second scan: Remove everything reserved that may overlap
|
||||
for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor*)(addr + i * descriptor_size);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
break;
|
||||
default:
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
remove_physical_memory_range(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
gKernelArgs.ignored_physical_memory
|
||||
+= initialPhysicalMemory - total_physical_memory();
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_memory_range,
|
||||
gKernelArgs.num_physical_memory_ranges);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_physical_allocated_list(size_t memory_map_size,
|
||||
efi_memory_descriptor* memory_map, size_t descriptor_size,
|
||||
uint32_t descriptor_version)
|
||||
{
|
||||
addr_t addr = (addr_t)memory_map;
|
||||
for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor*)(addr + i * descriptor_size);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderData: {
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
insert_physical_allocated_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_allocated_range,
|
||||
gKernelArgs.num_physical_allocated_ranges);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_mmu_init()
|
||||
{
|
||||
@ -459,7 +372,8 @@ arch_mmu_generate_post_efi_page_tables(size_t memory_map_size,
|
||||
arch_mmu_allocate_kernel_page_tables();
|
||||
|
||||
build_physical_memory_list(memory_map_size, memory_map,
|
||||
descriptor_size, descriptor_version);
|
||||
descriptor_size, descriptor_version,
|
||||
PHYSICAL_MEMORY_LOW, PHYSICAL_MEMORY_HIGH);
|
||||
|
||||
TRACE("Mapping Code & Data\n");
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <boot/stdio.h>
|
||||
|
||||
#include "efi_platform.h"
|
||||
#include "generic_mmu.h"
|
||||
#include "mmu.h"
|
||||
#include "serial.h"
|
||||
|
||||
@ -28,46 +29,6 @@ extern void arch_mmu_post_efi_setup(size_t memory_map_size, efi_memory_descripto
|
||||
extern void arch_mmu_setup_EL1(uint64 tcr);
|
||||
|
||||
|
||||
static const char*
|
||||
memory_region_type_str(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case EfiReservedMemoryType:
|
||||
return "ReservedMemoryType";
|
||||
case EfiLoaderCode:
|
||||
return "LoaderCode";
|
||||
case EfiLoaderData:
|
||||
return "LoaderData";
|
||||
case EfiBootServicesCode:
|
||||
return "BootServicesCode";
|
||||
case EfiBootServicesData:
|
||||
return "BootServicesData";
|
||||
case EfiRuntimeServicesCode:
|
||||
return "RuntimeServicesCode";
|
||||
case EfiRuntimeServicesData:
|
||||
return "RuntimeServicesData";
|
||||
case EfiConventionalMemory:
|
||||
return "ConventionalMemory";
|
||||
case EfiUnusableMemory:
|
||||
return "UnusableMemory";
|
||||
case EfiACPIReclaimMemory:
|
||||
return "ACPIReclaimMemory";
|
||||
case EfiACPIMemoryNVS:
|
||||
return "ACPIMemoryNVS";
|
||||
case EfiMemoryMappedIO:
|
||||
return "MMIO";
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
return "MMIOPortSpace";
|
||||
case EfiPalCode:
|
||||
return "PalCode";
|
||||
case EfiPersistentMemory:
|
||||
return "PersistentMemory";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_convert_kernel_args(void)
|
||||
{
|
||||
|
141
src/system/boot/platform/efi/arch/generic/generic_mmu.cpp
Normal file
141
src/system/boot/platform/efi/arch/generic/generic_mmu.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2022 Haiku, Inc. All rights reserved.
|
||||
* Released under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "generic_mmu.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
|
||||
void
|
||||
build_physical_memory_list(size_t memoryMapSize, efi_memory_descriptor* memoryMap,
|
||||
size_t descriptorSize, uint32_t descriptorVersion,
|
||||
uint64_t physicalMemoryLow, uint64_t physicalMemoryHigh)
|
||||
{
|
||||
addr_t addr = (addr_t)memoryMap;
|
||||
|
||||
gKernelArgs.num_physical_memory_ranges = 0;
|
||||
|
||||
// First scan: Add all usable ranges
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory: {
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t end = entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE;
|
||||
uint64_t originalSize = end - base;
|
||||
base = std::max(base, physicalMemoryLow);
|
||||
end = std::min(end, physicalMemoryHigh);
|
||||
|
||||
gKernelArgs.ignored_physical_memory
|
||||
+= originalSize - (max_c(end, base) - base);
|
||||
|
||||
if (base >= end)
|
||||
break;
|
||||
uint64_t size = end - base;
|
||||
|
||||
insert_physical_memory_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t initialPhysicalMemory = total_physical_memory();
|
||||
|
||||
// Second scan: Remove everything reserved that may overlap
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
break;
|
||||
default:
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
remove_physical_memory_range(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
gKernelArgs.ignored_physical_memory
|
||||
+= initialPhysicalMemory - total_physical_memory();
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_memory_range,
|
||||
gKernelArgs.num_physical_memory_ranges);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
build_physical_allocated_list(size_t memoryMapSize, efi_memory_descriptor* memoryMap,
|
||||
size_t descriptorSize, uint32_t descriptorVersion)
|
||||
{
|
||||
gKernelArgs.num_physical_allocated_ranges = 0;
|
||||
|
||||
addr_t addr = (addr_t)memoryMap;
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderData: {
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
insert_physical_allocated_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_allocated_range,
|
||||
gKernelArgs.num_physical_allocated_ranges);
|
||||
}
|
||||
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
24
src/system/boot/platform/efi/arch/generic/generic_mmu.h
Normal file
24
src/system/boot/platform/efi/arch/generic/generic_mmu.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2022 Haiku, Inc. All rights reserved.
|
||||
* Released under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef EFI_GENERIC_MMU_H
|
||||
#define EFI_GENERIC_MMU_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <efi/types.h>
|
||||
#include <efi/boot-services.h>
|
||||
|
||||
|
||||
void build_physical_memory_list(size_t memoryMapSize, efi_memory_descriptor *memoryMap,
|
||||
size_t descriptorSize, uint32_t descriptorVersion,
|
||||
uint64_t physicalMemoryLow, uint64_t physicalMemoryHigh);
|
||||
|
||||
void build_physical_allocated_list(size_t memoryMapSize, efi_memory_descriptor *memoryMap,
|
||||
size_t descriptorSize, uint32_t descriptorVersion);
|
||||
|
||||
const char* memory_region_type_str(int type);
|
||||
|
||||
|
||||
#endif /* EFI_GENERIC_MMU_H */
|
@ -1,6 +1,7 @@
|
||||
SubDir HAIKU_TOP src system boot platform efi arch x86 ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) $(DOTDOT) ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel platform ] ;
|
||||
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||
@ -28,8 +29,16 @@ for platform in [ MultiBootSubDirSetup efi ] {
|
||||
arch_timer.cpp
|
||||
;
|
||||
|
||||
local generic_src =
|
||||
generic_mmu.cpp
|
||||
;
|
||||
|
||||
BootMergeObject boot_platform_efi_x86.o :
|
||||
$(arch_src)
|
||||
$(generic_src)
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles $(generic_src) ]
|
||||
= [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <efi/boot-services.h>
|
||||
|
||||
#include "efi_platform.h"
|
||||
#include "generic_mmu.h"
|
||||
#include "mmu.h"
|
||||
|
||||
|
||||
@ -30,6 +31,10 @@
|
||||
//#define TRACE_MEMORY_MAP
|
||||
//#define TRACE_PAGE_DIRECTORY
|
||||
|
||||
// Ignore memory below 1M and above 64GB (maximum amount of physical memory on x86 with PAE)
|
||||
#define PHYSICAL_MEMORY_LOW 0x00100000
|
||||
#define PHYSICAL_MEMORY_HIGH 0x1000000000ull
|
||||
|
||||
#define VADDR_TO_PDENT(va) (((va) / B_PAGE_SIZE) / 1024)
|
||||
#define VADDR_TO_PTENT(va) (((va) / B_PAGE_SIZE) % 1024)
|
||||
#define X86_PDE_ADDRESS_MASK 0xfffff000
|
||||
@ -175,101 +180,6 @@ map_range(addr_t virtAddr, phys_addr_t physAddr, size_t size, uint32_t flags)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_physical_memory_list(size_t memoryMapSize,
|
||||
efi_memory_descriptor *memoryMap, size_t descriptorSize,
|
||||
uint32_t descriptorVersion)
|
||||
{
|
||||
addr_t addr = (addr_t)memoryMap;
|
||||
|
||||
gKernelArgs.num_physical_memory_ranges = 0;
|
||||
|
||||
// First scan: Add all usable ranges
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory: {
|
||||
// Usable memory.
|
||||
// Ignore memory below 1MB and above 512GB.
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t end = entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE;
|
||||
uint64_t originalSize = end - base;
|
||||
if (base < 0x100000)
|
||||
base = 0x100000;
|
||||
if (end > (512ull * 1024 * 1024 * 1024))
|
||||
end = 512ull * 1024 * 1024 * 1024;
|
||||
|
||||
gKernelArgs.ignored_physical_memory
|
||||
+= originalSize - (max_c(end, base) - base);
|
||||
|
||||
if (base >= end)
|
||||
break;
|
||||
uint64_t size = end - base;
|
||||
|
||||
insert_physical_memory_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t initialPhysicalMemory = total_physical_memory();
|
||||
|
||||
// Second scan: Remove everything reserved that may overlap
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
break;
|
||||
default:
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
remove_physical_memory_range(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
gKernelArgs.ignored_physical_memory
|
||||
+= initialPhysicalMemory - total_physical_memory();
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_memory_range,
|
||||
gKernelArgs.num_physical_memory_ranges);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_physical_allocated_list(size_t memoryMapSize,
|
||||
efi_memory_descriptor *memoryMap, size_t descriptorSize,
|
||||
uint32_t descriptorVersion)
|
||||
{
|
||||
addr_t addr = (addr_t)memoryMap;
|
||||
for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
|
||||
efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
|
||||
switch (entry->Type) {
|
||||
case EfiLoaderData: {
|
||||
uint64_t base = entry->PhysicalStart;
|
||||
uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
|
||||
insert_physical_allocated_range(base, size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
sort_address_ranges(gKernelArgs.physical_allocated_range,
|
||||
gKernelArgs.num_physical_allocated_ranges);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_mmu_post_efi_setup(size_t memoryMapSize,
|
||||
efi_memory_descriptor *memoryMap, size_t descriptorSize,
|
||||
@ -329,7 +239,8 @@ arch_mmu_generate_post_efi_page_tables(size_t memoryMapSize,
|
||||
uint32_t descriptorVersion)
|
||||
{
|
||||
build_physical_memory_list(memoryMapSize, memoryMap,
|
||||
descriptorSize, descriptorVersion);
|
||||
descriptorSize, descriptorVersion,
|
||||
PHYSICAL_MEMORY_LOW, PHYSICAL_MEMORY_HIGH);
|
||||
|
||||
//TODO: find out how to map EFI runtime services
|
||||
//they are not mapped for now because the kernel doesn't use them anyway
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <boot/stdio.h>
|
||||
|
||||
#include "efi_platform.h"
|
||||
#include "generic_mmu.h"
|
||||
#include "mmu.h"
|
||||
#include "serial.h"
|
||||
#include "smp.h"
|
||||
@ -50,46 +51,6 @@ arch_convert_kernel_args(void)
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
memory_region_type_str(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case EfiReservedMemoryType:
|
||||
return "ReservedMemoryType";
|
||||
case EfiLoaderCode:
|
||||
return "LoaderCode";
|
||||
case EfiLoaderData:
|
||||
return "LoaderData";
|
||||
case EfiBootServicesCode:
|
||||
return "BootServicesCode";
|
||||
case EfiBootServicesData:
|
||||
return "BootServicesData";
|
||||
case EfiRuntimeServicesCode:
|
||||
return "RuntimeServicesCode";
|
||||
case EfiRuntimeServicesData:
|
||||
return "RuntimeServicesData";
|
||||
case EfiConventionalMemory:
|
||||
return "ConventionalMemory";
|
||||
case EfiUnusableMemory:
|
||||
return "UnusableMemory";
|
||||
case EfiACPIReclaimMemory:
|
||||
return "ACPIReclaimMemory";
|
||||
case EfiACPIMemoryNVS:
|
||||
return "ACPIMemoryNVS";
|
||||
case EfiMemoryMappedIO:
|
||||
return "MMIO";
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
return "MMIOPortSpace";
|
||||
case EfiPalCode:
|
||||
return "PalCode";
|
||||
case EfiPersistentMemory:
|
||||
return "PersistentMemory";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_start_kernel(addr_t kernelEntry)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user