xref: /haiku/src/system/boot/platform/efi/arch/generic/generic_mmu.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2022 Haiku, Inc. All rights reserved.
3  * Released under the terms of the MIT License.
4  */
5 
6 #include "generic_mmu.h"
7 
8 #include <algorithm>
9 #include <boot/stage2.h>
10 
11 
12 void
13 build_physical_memory_list(size_t memoryMapSize, efi_memory_descriptor* memoryMap,
14 	size_t descriptorSize, uint32_t descriptorVersion,
15 	uint64_t physicalMemoryLow, uint64_t physicalMemoryHigh)
16 {
17 	addr_t addr = (addr_t)memoryMap;
18 
19 	gKernelArgs.num_physical_memory_ranges = 0;
20 
21 	// First scan: Add all usable ranges
22 	for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
23 		efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
24 		switch (entry->Type) {
25 			case EfiLoaderCode:
26 			case EfiLoaderData:
27 			case EfiBootServicesCode:
28 			case EfiBootServicesData:
29 			case EfiConventionalMemory: {
30 				uint64_t base = entry->PhysicalStart;
31 				uint64_t end = entry->PhysicalStart + entry->NumberOfPages * B_PAGE_SIZE;
32 				uint64_t originalSize = end - base;
33 				base = std::max(base, physicalMemoryLow);
34 				end = std::min(end, physicalMemoryHigh);
35 
36 				gKernelArgs.ignored_physical_memory
37 					+= originalSize - (max_c(end, base) - base);
38 
39 				if (base >= end)
40 					break;
41 				uint64_t size = end - base;
42 
43 				insert_physical_memory_range(base, size);
44 				break;
45 			}
46 			default:
47 				break;
48 		}
49 	}
50 
51 	uint64_t initialPhysicalMemory = total_physical_memory();
52 
53 	// Second scan: Remove everything reserved that may overlap
54 	for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
55 		efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
56 		switch (entry->Type) {
57 			case EfiLoaderCode:
58 			case EfiLoaderData:
59 			case EfiBootServicesCode:
60 			case EfiBootServicesData:
61 			case EfiConventionalMemory:
62 				break;
63 			default:
64 				uint64_t base = entry->PhysicalStart;
65 				uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
66 				remove_physical_memory_range(base, size);
67 		}
68 	}
69 
70 	gKernelArgs.ignored_physical_memory
71 		+= initialPhysicalMemory - total_physical_memory();
72 
73 	sort_address_ranges(gKernelArgs.physical_memory_range,
74 		gKernelArgs.num_physical_memory_ranges);
75 }
76 
77 
78 void
79 build_physical_allocated_list(size_t memoryMapSize, efi_memory_descriptor* memoryMap,
80 	size_t descriptorSize, uint32_t descriptorVersion)
81 {
82 	gKernelArgs.num_physical_allocated_ranges = 0;
83 
84 	addr_t addr = (addr_t)memoryMap;
85 	for (size_t i = 0; i < memoryMapSize / descriptorSize; ++i) {
86 		efi_memory_descriptor* entry = (efi_memory_descriptor *)(addr + i * descriptorSize);
87 		switch (entry->Type) {
88 			case EfiLoaderData: {
89 				uint64_t base = entry->PhysicalStart;
90 				uint64_t size = entry->NumberOfPages * B_PAGE_SIZE;
91 				insert_physical_allocated_range(base, size);
92 				break;
93 			}
94 			default:
95 				;
96 		}
97 	}
98 
99 	sort_address_ranges(gKernelArgs.physical_allocated_range,
100 		gKernelArgs.num_physical_allocated_ranges);
101 }
102 
103 
104 const char*
105 memory_region_type_str(int type)
106 {
107 	switch (type)	{
108 		case EfiReservedMemoryType:
109 			return "EfiReservedMemoryType";
110 		case EfiLoaderCode:
111 			return "EfiLoaderCode";
112 		case EfiLoaderData:
113 			return "EfiLoaderData";
114 		case EfiBootServicesCode:
115 			return "EfiBootServicesCode";
116 		case EfiBootServicesData:
117 			return "EfiBootServicesData";
118 		case EfiRuntimeServicesCode:
119 			return "EfiRuntimeServicesCode";
120 		case EfiRuntimeServicesData:
121 			return "EfiRuntimeServicesData";
122 		case EfiConventionalMemory:
123 			return "EfiConventionalMemory";
124 		case EfiUnusableMemory:
125 			return "EfiUnusableMemory";
126 		case EfiACPIReclaimMemory:
127 			return "EfiACPIReclaimMemory";
128 		case EfiACPIMemoryNVS:
129 			return "EfiACPIMemoryNVS";
130 		case EfiMemoryMappedIO:
131 			return "EfiMemoryMappedIO";
132 		case EfiMemoryMappedIOPortSpace:
133 			return "EfiMemoryMappedIOPortSpace";
134 		case EfiPalCode:
135 			return "EfiPalCode";
136 		case EfiPersistentMemory:
137 			return "EfiPersistentMemory";
138 		default:
139 			return "unknown";
140 	}
141 }
142