kern: implement enough of KPageTable to initialize a thread

This commit is contained in:
Michael Scire
2020-02-13 17:38:56 -08:00
parent c6d1579265
commit 8c93eb5712
31 changed files with 1475 additions and 270 deletions

View File

@@ -23,13 +23,13 @@ namespace ams::kern {
R_UNLESS(start_block != nullptr, svc::ResultOutOfResource());
/* Set our start and end. */
this->start = st;
this->end = nd;
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(this->start), PageSize));
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(this->end), PageSize));
this->start_address = st;
this->end_address = nd;
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(this->start_address), PageSize));
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(this->end_address), PageSize));
/* Initialize and insert the block. */
start_block->Initialize(this->start, (this->end - this->start) / PageSize, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None);
start_block->Initialize(this->start_address, (this->end_address - this->start_address) / PageSize, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None);
this->memory_block_tree.insert(*start_block);
return ResultSuccess();
@@ -47,6 +47,37 @@ namespace ams::kern {
MESOSPHERE_ASSERT(this->memory_block_tree.empty());
}
KProcessAddress KMemoryBlockManager::FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const {
if (num_pages > 0) {
const KProcessAddress region_end = region_start + region_num_pages * PageSize;
const KProcessAddress region_last = region_end - 1;
for (const_iterator it = this->FindIterator(region_start); it != this->memory_block_tree.cend(); it++) {
const KMemoryInfo info = it->GetMemoryInfo();
if (region_last < info.GetAddress()) {
break;
}
if (info.state != KMemoryState_Free) {
continue;
}
KProcessAddress area = (info.GetAddress() <= GetInteger(region_start)) ? region_start : info.GetAddress();
area += guard_pages * PageSize;
const KProcessAddress offset_area = util::AlignDown(GetInteger(area), alignment) + offset;
area = (area <= offset_area) ? offset_area : offset_area + alignment;
const KProcessAddress area_end = area + num_pages * PageSize + guard_pages * PageSize;
const KProcessAddress area_last = area_end - 1;
if (info.GetAddress() <= GetInteger(area) && area < area_last && area_last <= region_last && GetInteger(area_last) <= info.GetLastAddress()) {
return area;
}
}
}
return Null<KProcessAddress>;
}
void KMemoryBlockManager::Update(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr) {
/* Ensure for auditing that we never end up with an invalid tree. */
KScopedMemoryBlockManagerAuditor auditor(this);
@@ -101,7 +132,7 @@ namespace ams::kern {
/* Find the iterator now that we've updated. */
it = this->FindIterator(address);
if (address != this->start) {
if (address != this->start_address) {
it--;
}