1 using System;
2 using System.Collections;
3 using cmsx.machine;
4
5 namespace cmsx.kernel
6 {
7 public class AddressSpace
8 {
9 static nothrow AddressSpace() : nextAddressSpaceNumber(kernelAddressSpaceNumber + 1u)
10 {
11 }
12 public static nothrow ushort GetNextAddressSpaceNumber()
13 {
14 if (nextAddressSpaceNumber == kernelAddressSpaceNumber)
15 {
16 ++nextAddressSpaceNumber;
17 }
18 return nextAddressSpaceNumber++;
19 }
20 static ushort nextAddressSpaceNumber;
21 }
22
23 public nothrow ushort GetNextAddressSpaceNumber()
24 {
25 return AddressSpace.GetNextAddressSpaceNumber();
26 }
27
28 public class GlobalMemoryTable
29 {
30 static GlobalMemoryTable() : instance(new GlobalMemoryTable())
31 {
32 }
33 public static GlobalMemoryTable& Instance()
34 {
35 return *instance;
36 }
37 private GlobalMemoryTable()
38 {
39 }
40 public void AddMemoryTable(MemoryTable* memoryTable)
41 {
42 addressSpaceMemoryTableMap[memoryTable->addressSpaceNumber] = memoryTable;
43 }
44 public void RemoveMemoryTable(MemoryTable* memoryTable)
45 {
46 addressSpaceMemoryTableMap.Remove(memoryTable->addressSpaceNumber);
47 }
48 public nothrow MemoryTable* GetMemoryTable(ushort addressSpaceNumber) const
49 {
50 HashMap<ushort, MemoryTable*>.ConstIterator it = addressSpaceMemoryTableMap.CFind(addressSpaceNumber);
51 if (it != addressSpaceMemoryTableMap.CEnd())
52 {
53 return it->second;
54 }
55 else
56 {
57 return null;
58 }
59 }
60 private static UniquePtr<GlobalMemoryTable> instance;
61 private HashMap<ushort, MemoryTable*> addressSpaceMemoryTableMap;
62 }
63
64 public class MemoryTable
65 {
66 public ulong rootPageAddress;
67 public ushort addressSpaceNumber;
68 public SegmentDescriptor*[numSegments] segmentDescriptors;
69 public ulong virtualTranslationRegisterValue;
70 }
71
72 public nothrow ulong KernelGetMaxStackSize(ushort addressSpaceNumber)
73 {
74 MemoryTable* memoryTable = GlobalMemoryTable.Instance().GetMemoryTable(addressSpaceNumber);
75 if (memoryTable != null)
76 {
77 SegmentDescriptor* stackSegmentDescriptor = memoryTable->segmentDescriptors[stackSegmentIndex];
78 if (stackSegmentDescriptor != null)
79 {
80 return stackSegmentDescriptor->maxLength;
81 }
82 else
83 {
84 return 0u;
85 }
86 }
87 else
88 {
89 return 0u;
90 }
91 }
92
93 public nothrow bool KernelGrowStack(ushort addressSpaceNumber)
94 {
95 try
96 {
97 MemoryTable* memoryTable = GlobalMemoryTable.Instance().GetMemoryTable(addressSpaceNumber);
98 if (memoryTable != null)
99 {
100 SegmentDescriptor* stackSegmentDescriptor = memoryTable->segmentDescriptors[stackSegmentIndex];
101 if (stackSegmentDescriptor != null)
102 {
103 if (stackSegmentDescriptor->increment == 0u)
104 {
105 return false;
106 }
107 else if (stackSegmentDescriptor->length + stackSegmentDescriptor->increment <= stackSegmentDescriptor->maxLength)
108 {
109 GrowSegment(GetMachine().GetMemory(), *memoryTable, stackSegmentIndex, stackSegmentDescriptor->increment);
110 return true;
111 }
112 else
113 {
114 return false;
115 }
116 }
117 else
118 {
119 return false;
120 }
121 }
122 else
123 {
124 return false;
125 }
126 }
127 catch (const Exception& ex)
128 {
129 Kernel& kernel = Kernel.Instance();
130 ProcessTable& processTable = kernel.GetProcessTable();
131 Process* process = processTable.GetRunning();
132 Debugger* debugger = kernel.GetDebugger();
133 string errorlf = "KernelGrowStack failed: " + ex.Message() + "\n";
134 debugger->WriteOutput(cast<byte*>(cast<void*>(errorlf.Chars())), errorlf.Length());
135 debugger->Run(process);
136 return false;
137 }
138 return false;
139 }
140
141 public nothrow void DefaultInitializeMemoryTable(Machine& machine, MemoryTable& memoryTable)
142 {
143 Memory& mem = machine.GetMemory();
144 memoryTable.rootPageAddress = mem.AllocateRootPage();
145 memoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
146 memoryTable.segmentDescriptors[textSegmentIndex] = CreateSegmentDescriptor(pageSize, textSegmentBaseAddress, pageSize);
147 memoryTable.segmentDescriptors[dataSegmentIndex] = CreateSegmentDescriptor(0u, dataSegmentBaseAddress, pageSize);
148 memoryTable.segmentDescriptors[poolSegmentIndex] = CreateSegmentDescriptor(0u, poolSegmentBaseAddress, pageSize);
149 memoryTable.segmentDescriptors[stackSegmentIndex] = CreateSegmentDescriptor(0u, stackSegmentBaseAddress, pageSize);
150 memoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(memoryTable.rootPageAddress, memoryTable.addressSpaceNumber);
151 GlobalMemoryTable.Instance().AddMemoryTable(&memoryTable);
152 }
153
154 public nothrow void InitializeMemoryTable(Machine& machine, MemoryTable& memoryTable,
155 ulong textSegmentStartAddress, ulong textSegmentSize, ulong dataSegmentSize, ulong poolSegmentSize, ulong minStackSegmentSize, ulong maxStackSegmentSize, ulong stackSegmentIncrement)
156 {
157 Memory& mem = machine.GetMemory();
158 memoryTable.rootPageAddress = mem.AllocateRootPage();
159 memoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
160 if (textSegmentStartAddress == 0u)
161 {
162 textSegmentStartAddress = pageSize;
163 }
164 memoryTable.segmentDescriptors[textSegmentIndex] = CreateSegmentDescriptor(textSegmentStartAddress, textSegmentBaseAddress, textSegmentSize);
165 memoryTable.segmentDescriptors[dataSegmentIndex] = CreateSegmentDescriptor(0u, dataSegmentBaseAddress, dataSegmentSize);
166 memoryTable.segmentDescriptors[poolSegmentIndex] = CreateSegmentDescriptor(0u, poolSegmentBaseAddress, poolSegmentSize);
167 memoryTable.segmentDescriptors[stackSegmentIndex] = CreateSegmentDescriptor(0u, stackSegmentBaseAddress, minStackSegmentSize, maxStackSegmentSize, stackSegmentIncrement);
168 memoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(memoryTable.rootPageAddress, memoryTable.addressSpaceNumber);
169 GlobalMemoryTable.Instance().AddMemoryTable(&memoryTable);
170 }
171
172 public nothrow void InitializeMemoryTable(Machine& machine, MemoryTable& targetMemoryTable, const MemoryTable& sourceMemoryTable, ulong poolSegmentSize)
173 {
174 Memory& mem = machine.GetMemory();
175 targetMemoryTable.rootPageAddress = mem.AllocateRootPage();
176 targetMemoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
177 ShareSegment(mem, textSegmentIndex, targetMemoryTable, sourceMemoryTable, Protection.execute);
178 targetMemoryTable.segmentDescriptors[dataSegmentIndex] = CreateSegmentDescriptor(
179 sourceMemoryTable.segmentDescriptors[dataSegmentIndex]->startAddress,
180 sourceMemoryTable.segmentDescriptors[dataSegmentIndex]->baseAddress,
181 sourceMemoryTable.segmentDescriptors[dataSegmentIndex]->length);
182 targetMemoryTable.segmentDescriptors[poolSegmentIndex] = CreateSegmentDescriptor(0u, poolSegmentBaseAddress, poolSegmentSize);
183 targetMemoryTable.segmentDescriptors[stackSegmentIndex] = CreateSegmentDescriptor(
184 sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->startAddress,
185 sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->baseAddress,
186 sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->length,
187 sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->maxLength,
188 sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->increment);
189 targetMemoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(targetMemoryTable.rootPageAddress, targetMemoryTable.addressSpaceNumber);
190 GlobalMemoryTable.Instance().AddMemoryTable(&targetMemoryTable);
191 }
192
193 public nothrow void InitializeMemoryTableForCloning(Machine& machine, MemoryTable& memoryTable)
194 {
195 Memory& mem = machine.GetMemory();
196 memoryTable.rootPageAddress = mem.AllocateRootPage();
197 memoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
198 memoryTable.segmentDescriptors[textSegmentIndex] = null;
199 memoryTable.segmentDescriptors[dataSegmentIndex] = null;
200 memoryTable.segmentDescriptors[poolSegmentIndex] = null;
201 memoryTable.segmentDescriptors[stackSegmentIndex] = null;
202 memoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(memoryTable.rootPageAddress, memoryTable.addressSpaceNumber);
203 GlobalMemoryTable.Instance().AddMemoryTable(&memoryTable);
204 }
205
206 public nothrow void CalculatePageNumbers(const SegmentDescriptor& sd, ulong& startPageNumber, ulong& numPages)
207 {
208 ulong startAddress = sd.startAddress;
209 startPageNumber = GetPageNumber(startAddress);
210 ulong length = sd.length;
211 ulong segmentStart = startPageNumber * pageSize;
212 ulong segmentEnd = startAddress + length;
213 ulong segmentSize = segmentEnd - segmentStart;
214 numPages = 0u;
215 if (segmentSize > 0u)
216 {
217 numPages = (segmentSize - 1u) / pageSize + 1u;
218 }
219 }
220
221 public void AllocateMemoryPages(Memory& mem, ulong rootPageAddress, byte segmentIndex, ulong startPageNumber, ulong numPages, ushort addressSpaceNumber)
222 {
223 Protection protection = MakeDefaultPageProtection(segmentIndex);
224 ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
225 ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
226 ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
227 ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
228 ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
229 ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
230 ulong singleIndirectPageAddress = 0u;
231 ulong doubleIndirectPageAddress = 0u;
232 ulong tripleIndirectPageAddress = 0u;
233 ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
234 ulong pagesLeft = numPages;
235 ushort prevDigit0 = 0u;
236 ushort prevDigit1 = 0u;
237 ushort prevDigit2 = 0u;
238 while (pagesLeft > 0u)
239 {
240 if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
241 {
242 ulong entryAddress = rootPageAddress + 8u * entryNumber;
243 ulong pageAddress = mem.AllocatePage();
244 ulong pte = MakePageTableEntry(pageAddress, addressSpaceNumber, protection);
245 WriteMemoryULong(entryAddress, pte);
246 #if (MEMORY_DEBUG)
247 Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
248 #endif
249 }
250 else
251 {
252 if (singleIndirectEntryNumber != 0u)
253 {
254 #if (MEMORY_DEBUG)
255 Console.Out() << "indirect entries:" << endl();
256 #endif
257 ulong entryAddress = rootPageAddress + 8u * singleIndirectEntryNumber;
258 ulong pte = ReadMemoryULong(entryAddress);
259 singleIndirectPageAddress = 0u;
260 if (pte != 0u)
261 {
262 ulong pageAddress = 0u;
263 ushort pteAddressSpaceNumber = 0u;
264 Protection protection = Protection.notPresent;
265 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
266 if (protection != Protection.notPresent && pageAddress != 0u)
267 {
268 singleIndirectPageAddress = pageAddress;
269 }
270 }
271 if (singleIndirectPageAddress == 0u)
272 {
273 singleIndirectPageAddress = mem.AllocatePage();
274 pte = MakePageTableEntry(singleIndirectPageAddress, addressSpaceNumber, protection);
275 WriteMemoryULong(entryAddress, pte);
276 }
277 #if (MEMORY_DEBUG)
278 Console.Out() << "single indirect entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
279 #endif
280 singleIndirectEntryNumber = 0u;
281 }
282 ulong pageNum = entryNumber - firstIndirectEntryNumber;
283 ushort digit0 = 0u;
284 ushort digit1 = 0u;
285 ushort digit2 = 0u;
286 ExtractDigitsFromPageNumber(pageNum, digit0, digit1, digit2);
287 #if (MEMORY_DEBUG)
288 Console.Out() << "page number: " << ToHexString(pageNum) << ", d0: " << ToHexString(digit0) << ", d1: " << ToHexString(digit1) <<
289 ", d2: " << ToHexString(digit2) << endl();
290 #endif
291 if (digit2 == 0u && digit1 == 0u)
292 {
293 ulong entryAddress = singleIndirectPageAddress + 8u * digit0;
294 ulong pageAddress = mem.AllocatePage();
295 ulong pte = MakePageTableEntry(pageAddress, addressSpaceNumber, protection);
296 WriteMemoryULong(entryAddress, pte);
297 #if (MEMORY_DEBUG)
298 Console.Out() << "si-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
299 #endif
300 }
301 else if (digit2 == 0u && digit1 > 0u)
302 {
303 if (doubleIndirectEntryNumber != 0u)
304 {
305 ulong entryAddress = rootPageAddress + 8u * doubleIndirectEntryNumber;
306 ulong pte = ReadMemoryULong(entryAddress);
307 doubleIndirectPageAddress = 0u;
308 if (pte != 0u)
309 {
310 ulong pageAddress = 0u;
311 ushort pteAddressSpaceNumber = 0u;
312 Protection protection = Protection.notPresent;
313 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
314 if (protection != Protection.notPresent && pageAddress != 0u)
315 {
316 doubleIndirectPageAddress = pageAddress;
317 }
318 }
319 if (doubleIndirectPageAddress == 0u)
320 {
321 doubleIndirectPageAddress = mem.AllocatePage();
322 pte = MakePageTableEntry(doubleIndirectPageAddress, addressSpaceNumber, protection);
323 WriteMemoryULong(entryAddress, pte);
324 }
325 #if (MEMORY_DEBUG)
326 Console.Out() << "double indirect entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
327 #endif
328 doubleIndirectEntryNumber = 0u;
329 }
330 if (digit1 != prevDigit1)
331 {
332 ulong entryAddress = doubleIndirectPageAddress + 8u * digit1;
333 ulong pte = ReadMemoryULong(entryAddress);
334 singleIndirectPageAddress = 0u;
335 if (pte != 0u)
336 {
337 ulong pageAddress = 0u;
338 ushort pteAddressSpaceNumber = 0u;
339 Protection protection = Protection.notPresent;
340 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
341 if (protection != Protection.notPresent && pageAddress != 0u)
342 {
343 singleIndirectPageAddress = pageAddress;
344 }
345 }
346 if (singleIndirectPageAddress == 0u)
347 {
348 singleIndirectPageAddress = mem.AllocatePage();
349 pte = MakePageTableEntry(singleIndirectPageAddress, addressSpaceNumber, protection);
350 WriteMemoryULong(entryAddress, pte);
351 }
352 #if (MEMORY_DEBUG)
353 Console.Out() << "di-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
354 #endif
355 }
356 ulong siEntryAddress = singleIndirectPageAddress + 8u * digit0;
357 ulong siPageAddress = mem.AllocatePage();
358 ulong siPte = MakePageTableEntry(siPageAddress, addressSpaceNumber, protection);
359 WriteMemoryULong(siEntryAddress, siPte);
360 #if (MEMORY_DEBUG)
361 Console.Out() << "di-si-entry address: " << ToHexString(siEntryAddress) << ", page address: " << ToHexString(siPageAddress) << ", pte: " << ToHexString(siPte) << endl();
362 #endif
363 }
364 else if (digit2 > 0u)
365 {
366 if (tripleIndirectEntryNumber != 0u)
367 {
368 ulong entryAddress = rootPageAddress + 8u * tripleIndirectEntryNumber;
369 ulong pte = ReadMemoryULong(entryAddress);
370 tripleIndirectPageAddress = 0u;
371 if (pte != 0u)
372 {
373 ulong pageAddress = 0u;
374 ushort pteAddressSpaceNumber = 0u;
375 Protection protection = Protection.notPresent;
376 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
377 if (protection != Protection.notPresent && pageAddress != 0u)
378 {
379 tripleIndirectPageAddress = pageAddress;
380 }
381 }
382 if (tripleIndirectPageAddress == 0u)
383 {
384 tripleIndirectPageAddress = mem.AllocatePage();
385 pte = MakePageTableEntry(tripleIndirectPageAddress, addressSpaceNumber, protection);
386 WriteMemoryULong(entryAddress, pte);
387 }
388 #if (MEMORY_DEBUG)
389 Console.Out() << "triple indirect entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
390 #endif
391 tripleIndirectEntryNumber = 0u;
392 }
393 if (digit2 != prevDigit2)
394 {
395 ulong entryAddress = tripleIndirectPageAddress + 8u * digit2;
396 ulong pte = ReadMemoryULong(entryAddress);
397 doubleIndirectPageAddress = 0u;
398 if (pte != 0u)
399 {
400 ulong pageAddress = 0u;
401 ushort pteAddressSpaceNumber = 0u;
402 Protection protection = Protection.notPresent;
403 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
404 if (protection != Protection.notPresent && pageAddress != 0u)
405 {
406 doubleIndirectPageAddress = pageAddress;
407 }
408 }
409 if (doubleIndirectPageAddress == 0u)
410 {
411 doubleIndirectPageAddress = mem.AllocatePage();
412 pte = MakePageTableEntry(doubleIndirectPageAddress, addressSpaceNumber, protection);
413 WriteMemoryULong(entryAddress, pte);
414 }
415 #if (MEMORY_DEBUG)
416 Console.Out() << "ti-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
417 #endif
418 }
419 if (digit1 != prevDigit1)
420 {
421 ulong entryAddress = doubleIndirectPageAddress + 8u * digit1;
422 ulong pte = ReadMemoryULong(entryAddress);
423 singleIndirectPageAddress = 0u;
424 if (pte != 0u)
425 {
426 ulong pageAddress = 0u;
427 ushort pteAddressSpaceNumber = 0u;
428 Protection protection = Protection.notPresent;
429 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
430 if (protection != Protection.notPresent && pageAddress != 0u)
431 {
432 singleIndirectPageAddress = pageAddress;
433 }
434 }
435 if (singleIndirectPageAddress == 0u)
436 {
437 singleIndirectPageAddress = mem.AllocatePage();
438 pte = MakePageTableEntry(singleIndirectPageAddress, addressSpaceNumber, protection);
439 WriteMemoryULong(entryAddress, pte);
440 }
441 #if (MEMORY_DEBUG)
442 Console.Out() << "ti-di-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
443 #endif
444 }
445 ulong siEntryAddress = singleIndirectPageAddress + 8u * digit0;
446 ulong siPageAddress = mem.AllocatePage();
447 ulong siPte = MakePageTableEntry(siPageAddress, addressSpaceNumber, protection);
448 WriteMemoryULong(siEntryAddress, siPte);
449 #if (MEMORY_DEBUG)
450 Console.Out() << "ti-di-si-entry address: " << ToHexString(siEntryAddress) << ", page address: " << ToHexString(siPageAddress) << ", pte: " << ToHexString(siPte) << endl();
451 #endif
452 }
453 prevDigit0 = digit0;
454 prevDigit1 = digit1;
455 prevDigit2 = digit2;
456 }
457 ++entryNumber;
458 --pagesLeft;
459 }
460 }
461
462 public void FreeMemoryPages(Memory& mem, ulong rootPageAddress, byte segmentIndex, ulong startPageNumber, ulong numPages)
463 {
464 ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
465 ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
466 ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
467 ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
468 ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
469 ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
470 bool singleIndirectEntryAddressInitialized = false;
471 bool doubleIndirectEntryAddressInitialized = false;
472 bool tripleIndirectEntryAddressInitialized = false;
473 ulong singleIndirectPageAddress = 0u;
474 ulong singleIndirectEntryAddress = 0u;
475 ulong doubleIndirectPageAddress = 0u;
476 ulong doubleIndirectEntryAddress = 0u;
477 ulong diSingleIndirectPageAddress = 0u;
478 ulong diSingleIndirectEntryAddress = 0u;
479 ulong diSingleIndirectEntryNumber = 0u;
480 ulong tripleIndirectPageAddress = 0u;
481 ulong tripleIndirectEntryAddress = 0u;
482 ulong tiDoubleIndirectPageAddress = 0u;
483 ulong tiDoubleIndirectEntryAddress = 0u;
484 ulong tiDoubleIndirectEntryNumber = 0u;
485 ulong tiSingleIndirectPageAddress = 0u;
486 ulong tiSingleIndirectEntryAddress = 0u;
487 ulong tiSingleIndirectEntryNumber = 0u;
488 bool freeSingleIndirectPage = false;
489 bool freeDoubleIndirectPage = false;
490 bool freeTripleIndirectPage = false;
491 bool freeDiSingleIndirectPage = false;
492 bool freeTiDoubleIndirectPage = false;
493 bool freeTiSingleIndirectPage = false;
494 ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
495 ulong pagesLeft = numPages;
496 ushort prevDigit0 = 0u;
497 ushort prevDigit1 = 0u;
498 ushort prevDigit2 = 0u;
499 while (pagesLeft > 0u)
500 {
501 if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
502 {
503 ulong entryAddress = rootPageAddress + 8u * entryNumber;
504 ulong pte = ReadMemoryULong(entryAddress);
505 if (pte != 0u)
506 {
507 ulong pageAddress = 0u;
508 ushort pteAddressSpaceNumber = 0u;
509 Protection protection = Protection.notPresent;
510 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
511 if (protection != Protection.notPresent && pageAddress != 0u)
512 {
513 #if (MEMORY_DEBUG)
514 Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
515 #endif
516 mem.FreePage(pageAddress);
517 WriteMemoryULong(entryAddress, 0u);
518 }
519 }
520 }
521 else
522 {
523 if (!singleIndirectEntryAddressInitialized)
524 {
525 ulong entryAddress = rootPageAddress + 8u * singleIndirectEntryNumber;
526 singleIndirectEntryAddress = entryAddress;
527 ulong pte = ReadMemoryULong(entryAddress);
528 if (pte != 0u)
529 {
530 ulong pageAddress = 0u;
531 ushort pteAddressSpaceNumber = 0u;
532 Protection protection = Protection.notPresent;
533 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
534 if (protection != Protection.notPresent && pageAddress != 0u)
535 {
536 singleIndirectPageAddress = pageAddress;
537 }
538 else
539 {
540 singleIndirectPageAddress = 0u;
541 }
542 }
543 else
544 {
545 singleIndirectPageAddress = 0u;
546 }
547 singleIndirectEntryAddressInitialized = true;
548 }
549 ulong pageNum = entryNumber - firstIndirectEntryNumber;
550 ushort digit0 = 0u;
551 ushort digit1 = 0u;
552 ushort digit2 = 0u;
553 ExtractDigitsFromPageNumber(pageNum, digit0, digit1, digit2);
554 #if (MEMORY_DEBUG)
555 Console.Out() << "page number: " << ToHexString(pageNum) << ", d0: " << ToHexString(digit0) << ", d1: " << ToHexString(digit1) <<
556 ", d2: " << ToHexString(digit2) << endl();
557 #endif
558 if (digit2 == 0u && digit1 == 0u && singleIndirectPageAddress != 0u)
559 {
560 if (digit0 == 0u)
561 {
562 freeSingleIndirectPage = true;
563 }
564 ulong entryAddress = singleIndirectPageAddress + 8u * digit0;
565 ulong pte = ReadMemoryULong(entryAddress);
566 if (pte != 0u)
567 {
568 ulong pageAddress = 0u;
569 ushort pteAddressSpaceNumber = 0u;
570 Protection protection = Protection.notPresent;
571 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
572 if (protection != Protection.notPresent && pageAddress != 0u)
573 {
574 #if (MEMORY_DEBUG)
575 Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
576 #endif
577 mem.FreePage(pageAddress);
578 WriteMemoryULong(entryAddress, 0u);
579 }
580 }
581 if (digit0 == maxDigit && freeSingleIndirectPage)
582 {
583 mem.FreePage(singleIndirectPageAddress);
584 WriteMemoryULong(singleIndirectEntryAddress, 0u);
585 freeSingleIndirectPage = false;
586 }
587 }
588 else if (digit2 == 0u && digit1 > 0u)
589 {
590 if (digit1 == 1u && digit0 == 0u)
591 {
592 freeDoubleIndirectPage = true;
593 }
594 if (!doubleIndirectEntryAddressInitialized)
595 {
596 ulong entryAddress = rootPageAddress + 8u * doubleIndirectEntryNumber;
597 doubleIndirectEntryAddress = entryAddress;
598 ulong pte = ReadMemoryULong(entryAddress);
599 if (pte != 0u)
600 {
601 ulong pageAddress = 0u;
602 ushort pteAddressSpaceNumber = 0u;
603 Protection protection = Protection.notPresent;
604 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
605 if (protection != Protection.notPresent && pageAddress != 0u)
606 {
607 doubleIndirectPageAddress = pageAddress;
608 }
609 }
610 doubleIndirectEntryAddressInitialized = true;
611 }
612 if (doubleIndirectPageAddress != 0u)
613 {
614 if (digit1 != prevDigit1)
615 {
616 ulong entryAddress = doubleIndirectPageAddress + 8u * digit1;
617 diSingleIndirectEntryAddress = entryAddress;
618 diSingleIndirectEntryNumber = entryNumber;
619 ulong pte = ReadMemoryULong(entryAddress);
620 if (pte != 0u)
621 {
622 ulong pageAddress = 0u;
623 ushort pteAddressSpaceNumber = 0u;
624 Protection protection = Protection.notPresent;
625 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
626 if (protection != Protection.notPresent && pageAddress != 0u)
627 {
628 diSingleIndirectPageAddress = pageAddress;
629 }
630 else
631 {
632 diSingleIndirectPageAddress = 0u;
633 }
634 }
635 else
636 {
637 diSingleIndirectPageAddress = 0u;
638 }
639 }
640 if (diSingleIndirectPageAddress != 0u)
641 {
642 if (digit0 == 0u)
643 {
644 freeDiSingleIndirectPage = true;
645 }
646 ulong entryAddress = diSingleIndirectPageAddress + 8u * digit0;
647 ulong pte = ReadMemoryULong(entryAddress);
648 if (pte != 0u)
649 {
650 ulong pageAddress = 0u;
651 ushort pteAddressSpaceNumber = 0u;
652 Protection protection = Protection.notPresent;
653 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
654 if (protection != Protection.notPresent && pageAddress != 0u)
655 {
656 #if (MEMORY_DEBUG)
657 Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
658 #endif
659 mem.FreePage(pageAddress);
660 WriteMemoryULong(entryAddress, 0u);
661 }
662 }
663 if (digit0 == maxDigit && freeDiSingleIndirectPage)
664 {
665 mem.FreePage(diSingleIndirectPageAddress);
666 WriteMemoryULong(diSingleIndirectEntryAddress, 0u);
667 freeDiSingleIndirectPage = false;
668 }
669 }
670 if (digit1 == maxDigit && digit0 == maxDigit && freeDoubleIndirectPage)
671 {
672 mem.FreePage(doubleIndirectPageAddress);
673 WriteMemoryULong(doubleIndirectEntryAddress, 0u);
674 freeDoubleIndirectPage = false;
675 }
676 }
677 }
678 else if (digit2 > 0u)
679 {
680 if (digit2 == 1u && digit1 == 0u && digit0 == 0u)
681 {
682 freeTripleIndirectPage = true;
683 }
684 if (!tripleIndirectEntryAddressInitialized)
685 {
686 ulong entryAddress = rootPageAddress + 8u * tripleIndirectEntryNumber;
687 tripleIndirectEntryAddress = entryAddress;
688 ulong pte = ReadMemoryULong(entryAddress);
689 if (pte != 0u)
690 {
691 ulong pageAddress = 0u;
692 ushort pteAddressSpaceNumber = 0u;
693 Protection protection = Protection.notPresent;
694 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
695 if (protection != Protection.notPresent && pageAddress != 0u)
696 {
697 tripleIndirectPageAddress = pageAddress;
698 }
699 }
700 tripleIndirectEntryAddressInitialized = true;
701 }
702 if (tripleIndirectPageAddress != 0u)
703 {
704 if (digit2 != prevDigit2)
705 {
706 ulong entryAddress = tripleIndirectPageAddress + 8u * digit2;
707 tiDoubleIndirectEntryAddress = entryAddress;
708 tiDoubleIndirectEntryNumber = entryNumber;
709 ulong pte = ReadMemoryULong(entryAddress);
710 if (pte != 0u)
711 {
712 ulong pageAddress = 0u;
713 ushort pteAddressSpaceNumber = 0u;
714 Protection protection = Protection.notPresent;
715 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
716 if (protection != Protection.notPresent && pageAddress != 0u)
717 {
718 tiDoubleIndirectPageAddress = pageAddress;
719 }
720 else
721 {
722 tiDoubleIndirectPageAddress = 0u;
723 }
724 }
725 else
726 {
727 tiDoubleIndirectPageAddress = 0u;
728 }
729 }
730 if (tiDoubleIndirectPageAddress != 0u)
731 {
732 if (digit1 == 0u)
733 {
734 freeTiDoubleIndirectPage = true;
735 }
736 if (digit1 != prevDigit1)
737 {
738 ulong entryAddress = tiDoubleIndirectPageAddress + 8u * digit1;
739 tiSingleIndirectEntryAddress = entryAddress;
740 tiSingleIndirectEntryNumber = entryNumber;
741 ulong pte = ReadMemoryULong(entryAddress);
742 if (pte != 0u)
743 {
744 ulong pageAddress = 0u;
745 ushort pteAddressSpaceNumber = 0u;
746 Protection protection = Protection.notPresent;
747 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
748 if (protection != Protection.notPresent && pageAddress != 0u)
749 {
750 tiSingleIndirectPageAddress = pageAddress;
751 }
752 else
753 {
754 tiSingleIndirectPageAddress = 0u;
755 }
756 }
757 else
758 {
759 tiSingleIndirectPageAddress = 0u;
760 }
761 }
762 if (tiSingleIndirectPageAddress != 0u)
763 {
764 if (digit0 == 0u)
765 {
766 freeTiSingleIndirectPage = true;
767 }
768 ulong entryAddress = tiSingleIndirectPageAddress + 8u * digit0;
769 ulong pte = ReadMemoryULong(entryAddress);
770 if (pte != 0u)
771 {
772 ulong pageAddress = 0u;
773 ushort pteAddressSpaceNumber = 0u;
774 Protection protection = Protection.notPresent;
775 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
776 if (protection != Protection.notPresent && pageAddress != 0u)
777 {
778 #if (MEMORY_DEBUG)
779 Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
780 #endif
781 mem.FreePage(pageAddress);
782 WriteMemoryULong(entryAddress, 0u);
783 }
784 }
785 if (digit0 == maxDigit && freeTiSingleIndirectPage)
786 {
787 mem.FreePage(tiSingleIndirectPageAddress);
788 WriteMemoryULong(tiSingleIndirectEntryAddress, 0u);
789 freeTiSingleIndirectPage = false;
790 }
791 }
792 if (digit1 == maxDigit && digit0 == maxDigit && freeTiDoubleIndirectPage)
793 {
794 mem.FreePage(tiDoubleIndirectPageAddress);
795 WriteMemoryULong(tiDoubleIndirectEntryAddress, 0u);
796 freeTiDoubleIndirectPage = false;
797 }
798 }
799 if (pagesLeft == 1u && freeTripleIndirectPage)
800 {
801 mem.FreePage(tripleIndirectPageAddress);
802 WriteMemoryULong(tripleIndirectEntryAddress, 0u);
803 freeTripleIndirectPage = false;
804 }
805 }
806 }
807 prevDigit0 = digit0;
808 prevDigit1 = digit1;
809 prevDigit2 = digit2;
810 }
811 ++entryNumber;
812 --pagesLeft;
813 }
814 }
815
816 public void ShareMemoryPages(Memory& mem, ulong targetRootPageAddress, byte segmentIndex, ulong startPageNumber, ulong numPages, ushort targetAddressSpaceNumber,
817 ulong sourceRootPageAddress, ushort sourceAddressSpaceNumber, Protection pageProtection)
818 {
819 ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
820 ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
821 ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
822 ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
823 ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
824 ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
825 ulong sourceSingleIndirectPageAddress = 0u;
826 ulong targetSingleIndirectPageAddress = 0u;
827 ulong sourceDoubleIndirectPageAddress = 0u;
828 ulong targetDoubleIndirectPageAddress = 0u;
829 ulong sourceTripleIndirectPageAddress = 0u;
830 ulong targetTripleIndirectPageAddress = 0u;
831 ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
832 ulong pagesLeft = numPages;
833 ushort prevDigit0 = 0u;
834 ushort prevDigit1 = 0u;
835 ushort prevDigit2 = 0u;
836 while (pagesLeft > 0u)
837 {
838 if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
839 {
840 ulong targetEntryAddress = targetRootPageAddress + 8u * entryNumber;
841 ulong sourceEntryAddress = sourceRootPageAddress + 8u * entryNumber;
842 ulong pte = ReadMemoryULong(sourceEntryAddress);
843 if (pte != 0u)
844 {
845 ulong pageAddress = 0u;
846 ushort pteAddressSpaceNumber = 0u;
847 Protection protection = Protection.notPresent;
848 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
849 if (protection != Protection.notPresent && pageAddress != 0u)
850 {
851 mem.SharePage(pageAddress);
852 if (pageProtection == Protection.copyOnWrite)
853 {
854 pte = MakePageTableEntry(pageAddress, sourceAddressSpaceNumber, Protection.copyOnWrite);
855 WriteMemoryULong(sourceEntryAddress, pte);
856 }
857 pte = MakePageTableEntry(pageAddress, targetAddressSpaceNumber, pageProtection);
858 WriteMemoryULong(targetEntryAddress, pte);
859 }
860 }
861 }
862 else
863 {
864 if (singleIndirectEntryNumber != 0u)
865 {
866 ulong targetEntryAddress = targetRootPageAddress + 8u * singleIndirectEntryNumber;
867 ulong sourceEntryAddress = sourceRootPageAddress + 8u * singleIndirectEntryNumber;
868 ulong pte = ReadMemoryULong(sourceEntryAddress);
869 sourceSingleIndirectPageAddress = 0u;
870 if (pte != 0u)
871 {
872 ulong pageAddress = 0u;
873 ushort pteAddressSpaceNumber = 0u;
874 Protection protection = Protection.notPresent;
875 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
876 if (protection != Protection.notPresent && pageAddress != 0u)
877 {
878 sourceSingleIndirectPageAddress = pageAddress;
879 }
880 }
881 if (sourceSingleIndirectPageAddress != 0u)
882 {
883 targetSingleIndirectPageAddress = mem.AllocatePage();
884 pte = MakePageTableEntry(targetSingleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
885 WriteMemoryULong(targetEntryAddress, pte);
886 }
887 singleIndirectEntryNumber = 0u;
888 }
889 ulong pageNum = entryNumber - firstIndirectEntryNumber;
890 ushort digit0 = 0u;
891 ushort digit1 = 0u;
892 ushort digit2 = 0u;
893 ExtractDigitsFromPageNumber(pageNum, digit0, digit1, digit2);
894 if (digit2 == 0u && digit1 == 0u)
895 {
896 ulong sourceEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
897 ulong targetEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
898 ulong pte = ReadMemoryULong(sourceEntryAddress);
899 if (pte != 0u)
900 {
901 ulong pageAddress = 0u;
902 ushort pteAddressSpaceNumber = 0u;
903 Protection protection = Protection.notPresent;
904 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
905 if (protection != Protection.notPresent && pageAddress != 0u)
906 {
907 mem.SharePage(pageAddress);
908 if (pageProtection == Protection.copyOnWrite)
909 {
910 pte = MakePageTableEntry(pageAddress, sourceAddressSpaceNumber, Protection.copyOnWrite);
911 WriteMemoryULong(sourceEntryAddress, pte);
912 }
913 pte = MakePageTableEntry(pageAddress, targetAddressSpaceNumber, pageProtection);
914 WriteMemoryULong(targetEntryAddress, pte);
915 }
916 }
917 }
918 else if (digit2 == 0u && digit1 > 0u)
919 {
920 if (doubleIndirectEntryNumber != 0u)
921 {
922 ulong targetEntryAddress = targetRootPageAddress + 8u * doubleIndirectEntryNumber;
923 ulong sourceEntryAddress = sourceRootPageAddress + 8u * doubleIndirectEntryNumber;
924 ulong pte = ReadMemoryULong(sourceEntryAddress);
925 sourceDoubleIndirectPageAddress = 0u;
926 if (pte != 0u)
927 {
928 ulong pageAddress = 0u;
929 ushort pteAddressSpaceNumber = 0u;
930 Protection protection = Protection.notPresent;
931 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
932 if (protection != Protection.notPresent && pageAddress != 0u)
933 {
934 sourceDoubleIndirectPageAddress = pageAddress;
935 }
936 }
937 if (sourceDoubleIndirectPageAddress != 0u)
938 {
939 targetDoubleIndirectPageAddress = mem.AllocatePage();
940 pte = MakePageTableEntry(targetDoubleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
941 WriteMemoryULong(targetEntryAddress, pte);
942 }
943 doubleIndirectEntryNumber = 0u;
944 }
945 if (digit1 != prevDigit1)
946 {
947 ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
948 ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
949 ulong pte = ReadMemoryULong(sourceEntryAddress);
950 sourceSingleIndirectPageAddress = 0u;
951 if (pte != 0u)
952 {
953 ulong pageAddress = 0u;
954 ushort pteAddressSpaceNumber = 0u;
955 Protection protection = Protection.notPresent;
956 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
957 if (protection != Protection.notPresent && pageAddress != 0u)
958 {
959 sourceSingleIndirectPageAddress = pageAddress;
960 }
961 }
962 if (sourceSingleIndirectPageAddress != 0u)
963 {
964 targetSingleIndirectPageAddress = mem.AllocatePage();
965 pte = MakePageTableEntry(targetSingleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
966 WriteMemoryULong(targetEntryAddress, pte);
967 }
968 }
969 ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
970 ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
971 ulong pte = ReadMemoryULong(sourceSiEntryAddress);
972 if (pte != 0u)
973 {
974 ulong pageAddress = 0u;
975 ushort pteAddressSpaceNumber = 0u;
976 Protection protection = Protection.notPresent;
977 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
978 if (protection != Protection.notPresent && pageAddress != 0u)
979 {
980 mem.SharePage(pageAddress);
981 if (pageProtection == Protection.copyOnWrite)
982 {
983 pte = MakePageTableEntry(pageAddress, sourceAddressSpaceNumber, Protection.copyOnWrite);
984 WriteMemoryULong(sourceSiEntryAddress, pte);
985 }
986 pte = MakePageTableEntry(pageAddress, targetAddressSpaceNumber, pageProtection);
987 WriteMemoryULong(targetSiEntryAddress, pte);
988 }
989 }
990 }
991 else if (digit2 > 0u)
992 {
993 if (tripleIndirectEntryNumber != 0u)
994 {
995 ulong targetEntryAddress = targetRootPageAddress + 8u * tripleIndirectEntryNumber;
996 ulong sourceEntryAddress = sourceRootPageAddress + 8u * tripleIndirectEntryNumber;
997 ulong pte = ReadMemoryULong(sourceEntryAddress);
998 sourceTripleIndirectPageAddress = 0u;
999 if (pte != 0u)
1000 {
1001 ulong pageAddress = 0u;
1002 ushort pteAddressSpaceNumber = 0u;
1003 Protection protection = Protection.notPresent;
1004 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1005 if (protection != Protection.notPresent && pageAddress != 0u)
1006 {
1007 sourceTripleIndirectPageAddress = pageAddress;
1008 }
1009 }
1010 if (sourceTripleIndirectPageAddress != 0u)
1011 {
1012 targetTripleIndirectPageAddress = mem.AllocatePage();
1013 pte = MakePageTableEntry(targetTripleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1014 WriteMemoryULong(targetEntryAddress, pte);
1015 }
1016 tripleIndirectEntryNumber = 0u;
1017 }
1018 if (digit2 != prevDigit2)
1019 {
1020 ulong targetEntryAddress = targetTripleIndirectPageAddress + 8u * digit2;
1021 ulong sourceEntryAddress = sourceTripleIndirectPageAddress + 8u * digit2;
1022 ulong pte = ReadMemoryULong(sourceEntryAddress);
1023 sourceDoubleIndirectPageAddress = 0u;
1024 if (pte != 0u)
1025 {
1026 ulong pageAddress = 0u;
1027 ushort pteAddressSpaceNumber = 0u;
1028 Protection protection = Protection.notPresent;
1029 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1030 if (protection != Protection.notPresent && pageAddress != 0u)
1031 {
1032 sourceDoubleIndirectPageAddress = pageAddress;
1033 }
1034 }
1035 if (sourceDoubleIndirectPageAddress != 0u)
1036 {
1037 targetDoubleIndirectPageAddress = mem.AllocatePage();
1038 pte = MakePageTableEntry(targetDoubleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1039 WriteMemoryULong(targetEntryAddress, pte);
1040 }
1041 }
1042 if (digit1 != prevDigit1)
1043 {
1044 ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
1045 ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
1046 ulong pte = ReadMemoryULong(sourceEntryAddress);
1047 sourceSingleIndirectPageAddress = 0u;
1048 if (pte != 0u)
1049 {
1050 ulong pageAddress = 0u;
1051 ushort pteAddressSpaceNumber = 0u;
1052 Protection protection = Protection.notPresent;
1053 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1054 if (protection != Protection.notPresent && pageAddress != 0u)
1055 {
1056 sourceSingleIndirectPageAddress = pageAddress;
1057 }
1058 }
1059 if (sourceSingleIndirectPageAddress != 0u)
1060 {
1061 targetSingleIndirectPageAddress = mem.AllocatePage();
1062 pte = MakePageTableEntry(targetSingleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1063 WriteMemoryULong(targetEntryAddress, pte);
1064 }
1065 }
1066 ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1067 ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1068 ulong pte = ReadMemoryULong(sourceSiEntryAddress);
1069 if (pte != 0u)
1070 {
1071 ulong pageAddress = 0u;
1072 ushort pteAddressSpaceNumber = 0u;
1073 Protection protection = Protection.notPresent;
1074 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1075 if (protection != Protection.notPresent && pageAddress != 0u)
1076 {
1077 mem.SharePage(pageAddress);
1078 if (pageProtection == Protection.copyOnWrite)
1079 {
1080 pte = MakePageTableEntry(pageAddress, sourceAddressSpaceNumber, Protection.copyOnWrite);
1081 WriteMemoryULong(sourceSiEntryAddress, pte);
1082 }
1083 pte = MakePageTableEntry(pageAddress, targetAddressSpaceNumber, pageProtection);
1084 WriteMemoryULong(targetSiEntryAddress, pte);
1085 }
1086 }
1087 }
1088 prevDigit0 = digit0;
1089 prevDigit1 = digit1;
1090 prevDigit2 = digit2;
1091 }
1092 ++entryNumber;
1093 --pagesLeft;
1094 }
1095 }
1096
1097 public void CopyMemoryPages(Memory& mem, ulong targetRootPageAddress, byte segmentIndex, ulong startPageNumber, ulong numPages, ushort targetAddressSpaceNumber,
1098 ulong sourceRootPageAddress, ushort sourceAddressSpaceNumber, Protection pageProtection)
1099 {
1100 ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
1101 ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
1102 ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
1103 ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
1104 ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
1105 ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
1106 ulong sourceSingleIndirectPageAddress = 0u;
1107 ulong targetSingleIndirectPageAddress = 0u;
1108 ulong sourceDoubleIndirectPageAddress = 0u;
1109 ulong targetDoubleIndirectPageAddress = 0u;
1110 ulong sourceTripleIndirectPageAddress = 0u;
1111 ulong targetTripleIndirectPageAddress = 0u;
1112 ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
1113 ulong pagesLeft = numPages;
1114 ushort prevDigit0 = 0u;
1115 ushort prevDigit1 = 0u;
1116 ushort prevDigit2 = 0u;
1117 while (pagesLeft > 0u)
1118 {
1119 if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
1120 {
1121 ulong targetEntryAddress = targetRootPageAddress + 8u * entryNumber;
1122 ulong sourceEntryAddress = sourceRootPageAddress + 8u * entryNumber;
1123 ulong pte = ReadMemoryULong(sourceEntryAddress);
1124 if (pte != 0u)
1125 {
1126 ulong sourcePageAddress = 0u;
1127 ushort pteAddressSpaceNumber = 0u;
1128 Protection protection = Protection.notPresent;
1129 UnpackPageTableEntry(pte, sourcePageAddress, pteAddressSpaceNumber, protection);
1130 if (protection != Protection.notPresent && sourcePageAddress != 0u)
1131 {
1132 ulong targetPageAddress = mem.AllocatePage();
1133 mem.CopyPage(sourcePageAddress, targetPageAddress);
1134 pte = MakePageTableEntry(targetPageAddress, targetAddressSpaceNumber, protection);
1135 WriteMemoryULong(targetEntryAddress, pte);
1136 }
1137 }
1138 }
1139 else
1140 {
1141 if (singleIndirectEntryNumber != 0u)
1142 {
1143 ulong targetEntryAddress = targetRootPageAddress + 8u * singleIndirectEntryNumber;
1144 ulong sourceEntryAddress = sourceRootPageAddress + 8u * singleIndirectEntryNumber;
1145 ulong pte = ReadMemoryULong(sourceEntryAddress);
1146 sourceSingleIndirectPageAddress = 0u;
1147 if (pte != 0u)
1148 {
1149 ulong pageAddress = 0u;
1150 ushort pteAddressSpaceNumber = 0u;
1151 Protection protection = Protection.notPresent;
1152 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1153 if (protection != Protection.notPresent && pageAddress != 0u)
1154 {
1155 sourceSingleIndirectPageAddress = pageAddress;
1156 }
1157 }
1158 if (sourceSingleIndirectPageAddress != 0u)
1159 {
1160 targetSingleIndirectPageAddress = mem.AllocatePage();
1161 pte = MakePageTableEntry(targetSingleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1162 WriteMemoryULong(targetEntryAddress, pte);
1163 }
1164 singleIndirectEntryNumber = 0u;
1165 }
1166 ulong pageNum = entryNumber - firstIndirectEntryNumber;
1167 ushort digit0 = 0u;
1168 ushort digit1 = 0u;
1169 ushort digit2 = 0u;
1170 ExtractDigitsFromPageNumber(pageNum, digit0, digit1, digit2);
1171 if (digit2 == 0u && digit1 == 0u)
1172 {
1173 ulong sourceEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1174 ulong targetEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1175 ulong pte = ReadMemoryULong(sourceEntryAddress);
1176 if (pte != 0u)
1177 {
1178 ulong sourcePageAddress = 0u;
1179 ushort pteAddressSpaceNumber = 0u;
1180 Protection protection = Protection.notPresent;
1181 UnpackPageTableEntry(pte, sourcePageAddress, pteAddressSpaceNumber, protection);
1182 if (protection != Protection.notPresent && sourcePageAddress != 0u)
1183 {
1184 ulong targetPageAddress = mem.AllocatePage();
1185 mem.CopyPage(sourcePageAddress, targetPageAddress);
1186 pte = MakePageTableEntry(targetPageAddress, targetAddressSpaceNumber, protection);
1187 WriteMemoryULong(targetEntryAddress, pte);
1188 }
1189 }
1190 }
1191 else if (digit2 == 0u && digit1 > 0u)
1192 {
1193 if (doubleIndirectEntryNumber != 0u)
1194 {
1195 ulong targetEntryAddress = targetRootPageAddress + 8u * doubleIndirectEntryNumber;
1196 ulong sourceEntryAddress = sourceRootPageAddress + 8u * doubleIndirectEntryNumber;
1197 ulong pte = ReadMemoryULong(sourceEntryAddress);
1198 sourceDoubleIndirectPageAddress = 0u;
1199 if (pte != 0u)
1200 {
1201 ulong pageAddress = 0u;
1202 ushort pteAddressSpaceNumber = 0u;
1203 Protection protection = Protection.notPresent;
1204 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1205 if (protection != Protection.notPresent && pageAddress != 0u)
1206 {
1207 sourceDoubleIndirectPageAddress = pageAddress;
1208 }
1209 }
1210 if (sourceDoubleIndirectPageAddress != 0u)
1211 {
1212 targetDoubleIndirectPageAddress = mem.AllocatePage();
1213 pte = MakePageTableEntry(targetDoubleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1214 WriteMemoryULong(targetEntryAddress, pte);
1215 }
1216 doubleIndirectEntryNumber = 0u;
1217 }
1218 if (digit1 != prevDigit1)
1219 {
1220 ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
1221 ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
1222 ulong pte = ReadMemoryULong(sourceEntryAddress);
1223 sourceSingleIndirectPageAddress = 0u;
1224 if (pte != 0u)
1225 {
1226 ulong pageAddress = 0u;
1227 ushort pteAddressSpaceNumber = 0u;
1228 Protection protection = Protection.notPresent;
1229 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1230 if (protection != Protection.notPresent && pageAddress != 0u)
1231 {
1232 sourceSingleIndirectPageAddress = pageAddress;
1233 }
1234 }
1235 if (sourceSingleIndirectPageAddress != 0u)
1236 {
1237 targetSingleIndirectPageAddress = mem.AllocatePage();
1238 pte = MakePageTableEntry(targetSingleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1239 WriteMemoryULong(targetEntryAddress, pte);
1240 }
1241 }
1242 ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1243 ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1244 ulong pte = ReadMemoryULong(sourceSiEntryAddress);
1245 if (pte != 0u)
1246 {
1247 ulong sourcePageAddress = 0u;
1248 ushort pteAddressSpaceNumber = 0u;
1249 Protection protection = Protection.notPresent;
1250 UnpackPageTableEntry(pte, sourcePageAddress, pteAddressSpaceNumber, protection);
1251 if (protection != Protection.notPresent && sourcePageAddress != 0u)
1252 {
1253 ulong targetPageAddress = mem.AllocatePage();
1254 mem.CopyPage(sourcePageAddress, targetPageAddress);
1255 pte = MakePageTableEntry(targetPageAddress, targetAddressSpaceNumber, protection);
1256 WriteMemoryULong(targetSiEntryAddress, pte);
1257 }
1258 }
1259 }
1260 else if (digit2 > 0u)
1261 {
1262 if (tripleIndirectEntryNumber != 0u)
1263 {
1264 ulong targetEntryAddress = targetRootPageAddress + 8u * tripleIndirectEntryNumber;
1265 ulong sourceEntryAddress = sourceRootPageAddress + 8u * tripleIndirectEntryNumber;
1266 ulong pte = ReadMemoryULong(sourceEntryAddress);
1267 sourceTripleIndirectPageAddress = 0u;
1268 if (pte != 0u)
1269 {
1270 ulong pageAddress = 0u;
1271 ushort pteAddressSpaceNumber = 0u;
1272 Protection protection = Protection.notPresent;
1273 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1274 if (protection != Protection.notPresent && pageAddress != 0u)
1275 {
1276 sourceTripleIndirectPageAddress = pageAddress;
1277 }
1278 }
1279 if (sourceTripleIndirectPageAddress != 0u)
1280 {
1281 targetTripleIndirectPageAddress = mem.AllocatePage();
1282 pte = MakePageTableEntry(targetTripleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1283 WriteMemoryULong(targetEntryAddress, pte);
1284 }
1285 tripleIndirectEntryNumber = 0u;
1286 }
1287 if (digit2 != prevDigit2)
1288 {
1289 ulong targetEntryAddress = targetTripleIndirectPageAddress + 8u * digit2;
1290 ulong sourceEntryAddress = sourceTripleIndirectPageAddress + 8u * digit2;
1291 ulong pte = ReadMemoryULong(sourceEntryAddress);
1292 sourceDoubleIndirectPageAddress = 0u;
1293 if (pte != 0u)
1294 {
1295 ulong pageAddress = 0u;
1296 ushort pteAddressSpaceNumber = 0u;
1297 Protection protection = Protection.notPresent;
1298 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1299 if (protection != Protection.notPresent && pageAddress != 0u)
1300 {
1301 sourceDoubleIndirectPageAddress = pageAddress;
1302 }
1303 }
1304 if (sourceDoubleIndirectPageAddress != 0u)
1305 {
1306 targetDoubleIndirectPageAddress = mem.AllocatePage();
1307 pte = MakePageTableEntry(targetDoubleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1308 WriteMemoryULong(targetEntryAddress, pte);
1309 }
1310 }
1311 if (digit1 != prevDigit1)
1312 {
1313 ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
1314 ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
1315 ulong pte = ReadMemoryULong(sourceEntryAddress);
1316 sourceSingleIndirectPageAddress = 0u;
1317 if (pte != 0u)
1318 {
1319 ulong pageAddress = 0u;
1320 ushort pteAddressSpaceNumber = 0u;
1321 Protection protection = Protection.notPresent;
1322 UnpackPageTableEntry(pte, pageAddress, pteAddressSpaceNumber, protection);
1323 if (protection != Protection.notPresent && pageAddress != 0u)
1324 {
1325 sourceSingleIndirectPageAddress = pageAddress;
1326 }
1327 }
1328 if (sourceSingleIndirectPageAddress != 0u)
1329 {
1330 targetSingleIndirectPageAddress = mem.AllocatePage();
1331 pte = MakePageTableEntry(targetSingleIndirectPageAddress, targetAddressSpaceNumber, pageProtection);
1332 WriteMemoryULong(targetEntryAddress, pte);
1333 }
1334 }
1335 ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1336 ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1337 ulong pte = ReadMemoryULong(sourceSiEntryAddress);
1338 if (pte != 0u)
1339 {
1340 ulong sourcePageAddress = 0u;
1341 ushort pteAddressSpaceNumber = 0u;
1342 Protection protection = Protection.notPresent;
1343 UnpackPageTableEntry(pte, sourcePageAddress, pteAddressSpaceNumber, protection);
1344 if (protection != Protection.notPresent && sourcePageAddress != 0u)
1345 {
1346 ulong targetPageAddress = mem.AllocatePage();
1347 mem.CopyPage(sourcePageAddress, targetPageAddress);
1348 pte = MakePageTableEntry(targetPageAddress, targetAddressSpaceNumber, protection);
1349 WriteMemoryULong(targetSiEntryAddress, pte);
1350 }
1351 }
1352 }
1353 prevDigit0 = digit0;
1354 prevDigit1 = digit1;
1355 prevDigit2 = digit2;
1356 }
1357 ++entryNumber;
1358 --pagesLeft;
1359 }
1360 }
1361
1362 public void AllocateMemory(Memory& mem, const MemoryTable& memoryTable, bool skipTextSegment)
1363 {
1364 mem.ClearTranslationCache(memoryTable.addressSpaceNumber);
1365 for (byte i = 0u; i < numSegments; ++i;)
1366 {
1367 if (skipTextSegment && i == textSegmentIndex) continue;
1368 SegmentDescriptor* sd = memoryTable.segmentDescriptors[i];
1369 if (sd != null)
1370 {
1371 ulong startPageNumber = 0u;
1372 ulong numPages = 0u;
1373 CalculatePageNumbers(*sd, startPageNumber, numPages);
1374 AllocateMemoryPages(mem, memoryTable.rootPageAddress, i, startPageNumber, numPages, memoryTable.addressSpaceNumber);
1375 }
1376 }
1377 }
1378
1379 public void FreeMemory(Memory& mem, MemoryTable& memoryTable)
1380 {
1381 for (byte i = 0u; i < numSegments; ++i;)
1382 {
1383 SegmentDescriptor* sd = memoryTable.segmentDescriptors[i];
1384 if (sd != null)
1385 {
1386 #assert(sd->useCount > 0);
1387 sd->useCount = sd->useCount - 1u;
1388 if (sd->useCount == 0u)
1389 {
1390 ulong startPageNumber = 0u;
1391 ulong numPages = 0u;
1392 CalculatePageNumbers(*sd, startPageNumber, numPages);
1393 FreeMemoryPages(mem, memoryTable.rootPageAddress, i, startPageNumber, numPages);
1394 FreeSegmentDescriptor(sd);
1395 }
1396 memoryTable.segmentDescriptors[i] = null;
1397 }
1398 }
1399 mem.FreeRootPage(memoryTable.rootPageAddress);
1400 memoryTable.rootPageAddress = 0u;
1401 mem.DisposeTranslationCache(memoryTable.addressSpaceNumber);
1402 GlobalMemoryTable.Instance().RemoveMemoryTable(&memoryTable);
1403 }
1404
1405 public void CloneMemory(Memory& mem, MemoryTable& targetMemoryTable, MemoryTable& sourceMemoryTable)
1406 {
1407 mem.ClearTranslationCache(sourceMemoryTable.addressSpaceNumber);
1408 mem.ClearTranslationCache(targetMemoryTable.addressSpaceNumber);
1409 for (byte i = 0u; i < numSegments; ++i;)
1410 {
1411 SegmentDescriptor* sd = sourceMemoryTable.segmentDescriptors[i];
1412 if (sd != null)
1413 {
1414 if (i == textSegmentIndex)
1415 {
1416 ShareSegment(mem, i, targetMemoryTable, sourceMemoryTable, MakeDefaultPageProtection(i));
1417 }
1418 else
1419 {
1420 CopySegment(mem, i, targetMemoryTable, sourceMemoryTable, MakeDefaultPageProtection(i));
1421 }
1422 }
1423 }
1424 }
1425
1426 public void GrowSegment(Memory& mem, MemoryTable& memoryTable, byte segmentIndex, ulong numBytes)
1427 {
1428 if (segmentIndex >= numSegments)
1429 {
1430 throw Exception("invalid segment index " + ToString(segmentIndex));
1431 }
1432 if (numBytes > 0u)
1433 {
1434 SegmentDescriptor* sd = memoryTable.segmentDescriptors[segmentIndex];
1435 if (sd == null)
1436 {
1437 throw Exception("segment desciptor for segment index " + ToString(segmentIndex) + " is null");
1438 }
1439 ulong startPageNumber = 0u;
1440 ulong numPages = 0u;
1441 CalculatePageNumbers(*sd, startPageNumber, numPages);
1442 startPageNumber = startPageNumber + numPages;
1443 numPages = 0u;
1444 if (numBytes > 0)
1445 {
1446 numPages = (numBytes - 1u) / pageSize + 1u;
1447 }
1448 AllocateMemoryPages(mem, memoryTable.rootPageAddress, segmentIndex, startPageNumber, numPages, memoryTable.addressSpaceNumber);
1449 ulong oldLength = sd->length;
1450 ulong newLength = oldLength + numPages * pageSize;
1451 sd->length = newLength;
1452 mem.ClearTranslationCache(memoryTable.addressSpaceNumber);
1453 }
1454 }
1455
1456 public void ShrinkSegment(Memory& mem, MemoryTable& memoryTable, byte segmentIndex, ulong numBytes)
1457 {
1458 if (segmentIndex >= numSegments)
1459 {
1460 throw Exception("invalid segment index " + ToString(segmentIndex));
1461 }
1462 if (numBytes >= 0)
1463 {
1464 SegmentDescriptor* sd = memoryTable.segmentDescriptors[segmentIndex];
1465 if (sd == null)
1466 {
1467 throw Exception("segment descriptor for segment index " + ToString(segmentIndex) + " is null");
1468 }
1469 ulong startPageNumber = 0u;
1470 ulong numPages = 0u;
1471 CalculatePageNumbers(*sd, startPageNumber, numPages);
1472 startPageNumber = startPageNumber + numPages;
1473 numPages = 0u;
1474 if (numBytes > 0)
1475 {
1476 numPages = (numBytes - 1u) / pageSize + 1u;
1477 }
1478 if (startPageNumber < numPages)
1479 {
1480 throw Exception("internal error: start page number less than number of pages");
1481 }
1482 startPageNumber = startPageNumber - numPages;
1483 FreeMemoryPages(mem, memoryTable.rootPageAddress, segmentIndex, startPageNumber, numPages);
1484 ulong oldLength = sd->length;
1485 ulong newLength = oldLength - numPages * pageSize;
1486 sd->length = newLength;
1487 mem.ClearTranslationCache(memoryTable.addressSpaceNumber);
1488 }
1489 }
1490
1491 public void ShareSegment(Memory& mem, byte segmentIndex, MemoryTable& targetMemoryTable, const MemoryTable& sourceMemoryTable, Protection protection)
1492 {
1493 if (segmentIndex >= numSegments)
1494 {
1495 throw Exception("share segment: invalid segment index " + ToString(segmentIndex));
1496 }
1497 if (targetMemoryTable.segmentDescriptors[segmentIndex] != null)
1498 {
1499 throw Exception("internal error: share segment: target segment descriptor not null");
1500 }
1501 SegmentDescriptor* sourceSegmentDescriptor = sourceMemoryTable.segmentDescriptors[segmentIndex];
1502 if (sourceSegmentDescriptor == null)
1503 {
1504 throw Exception("internal error: share segment: source segment descriptor is null");
1505 }
1506 if (targetMemoryTable.rootPageAddress == 0u)
1507 {
1508 targetMemoryTable.rootPageAddress = mem.AllocateRootPage();
1509 }
1510 SegmentDescriptor* targetSegmentDescriptor = CreateSegmentDescriptor(sourceSegmentDescriptor->startAddress, sourceSegmentDescriptor->baseAddress, sourceSegmentDescriptor->length);
1511 if (targetSegmentDescriptor == null)
1512 {
1513 throw Exception("internal error: share segment: target segment descriptor is null");
1514 }
1515 targetMemoryTable.segmentDescriptors[segmentIndex] = targetSegmentDescriptor;
1516 ulong startPageNumber = 0u;
1517 ulong numPages = 0u;
1518 CalculatePageNumbers(*targetSegmentDescriptor, startPageNumber, numPages);
1519 ShareMemoryPages(mem, targetMemoryTable.rootPageAddress, segmentIndex, startPageNumber, numPages, targetMemoryTable.addressSpaceNumber,
1520 sourceMemoryTable.rootPageAddress, sourceMemoryTable.addressSpaceNumber, protection);
1521 }
1522
1523 public void CopySegment(Memory& mem, byte segmentIndex, MemoryTable& targetMemoryTable, const MemoryTable& sourceMemoryTable, Protection protection)
1524 {
1525 if (segmentIndex >= numSegments)
1526 {
1527 throw Exception("copy segment: invalid segment index " + ToString(segmentIndex));
1528 }
1529 if (targetMemoryTable.segmentDescriptors[segmentIndex] != null)
1530 {
1531 throw Exception("internal error: copy segment: target segment descriptor not null");
1532 }
1533 SegmentDescriptor* sourceSegmentDescriptor = sourceMemoryTable.segmentDescriptors[segmentIndex];
1534 if (sourceSegmentDescriptor == null)
1535 {
1536 throw Exception("internal error: copy segment: source segment descriptor is null");
1537 }
1538 if (targetMemoryTable.rootPageAddress == 0u)
1539 {
1540 targetMemoryTable.rootPageAddress = mem.AllocateRootPage();
1541 }
1542 SegmentDescriptor* targetSegmentDescriptor = CreateSegmentDescriptor(sourceSegmentDescriptor->startAddress, sourceSegmentDescriptor->baseAddress, sourceSegmentDescriptor->length);
1543 if (targetSegmentDescriptor == null)
1544 {
1545 throw Exception("internal error: copy segment: target segment descriptor is null");
1546 }
1547 targetMemoryTable.segmentDescriptors[segmentIndex] = targetSegmentDescriptor;
1548 ulong startPageNumber = 0u;
1549 ulong numPages = 0u;
1550 CalculatePageNumbers(*targetSegmentDescriptor, startPageNumber, numPages);
1551 CopyMemoryPages(mem, targetMemoryTable.rootPageAddress, segmentIndex, startPageNumber, numPages, targetMemoryTable.addressSpaceNumber,
1552 sourceMemoryTable.rootPageAddress, sourceMemoryTable.addressSpaceNumber, protection);
1553 }
1554 }