mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-10 07:06:34 +00:00
kern: resolve MESOSPHERE_UNIMPLEMENTEDs other than UserException
This commit is contained in:
parent
325802e29d
commit
c9f8252577
4 changed files with 85 additions and 12 deletions
|
@ -41,8 +41,6 @@ namespace ams::kern::arch::arm64 {
|
||||||
cpu::InvalidateEntireTlb();
|
cpu::InvalidateEntireTlb();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finalize(s32 core_id);
|
|
||||||
|
|
||||||
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||||
return this->page_table.MapPages(out_addr, num_pages, alignment, phys_addr, region_start, region_num_pages, state, perm);
|
return this->page_table.MapPages(out_addr, num_pages, alignment, phys_addr, region_start, region_num_pages, state, perm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,4 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KSupervisorPageTable::Finalize(s32 core_id) {
|
|
||||||
MESOSPHERE_UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1647,11 +1647,85 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
|
Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
|
||||||
MESOSPHERE_UNIMPLEMENTED();
|
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(phys_addr), PageSize));
|
||||||
|
MESOSPHERE_ASSERT(util::IsAligned(size, PageSize));
|
||||||
|
MESOSPHERE_ASSERT(size > 0);
|
||||||
|
R_UNLESS(phys_addr < phys_addr + size, svc::ResultInvalidAddress());
|
||||||
|
const size_t num_pages = size / PageSize;
|
||||||
|
const KPhysicalAddress last = phys_addr + size - 1;
|
||||||
|
|
||||||
|
/* Get region extents. */
|
||||||
|
const KProcessAddress region_start = this->GetRegionAddress(KMemoryState_Static);
|
||||||
|
const size_t region_size = this->GetRegionSize(KMemoryState_Static);
|
||||||
|
const size_t region_num_pages = region_size / PageSize;
|
||||||
|
|
||||||
|
/* Locate the memory region. */
|
||||||
|
auto region_it = KMemoryLayout::FindContainingRegion(phys_addr);
|
||||||
|
const auto end_it = KMemoryLayout::GetEnd(phys_addr);
|
||||||
|
R_UNLESS(region_it != end_it, svc::ResultInvalidAddress());
|
||||||
|
|
||||||
|
MESOSPHERE_ASSERT(region_it->Contains(GetInteger(phys_addr)));
|
||||||
|
R_UNLESS(GetInteger(last) <= region_it->GetLastAddress(), svc::ResultInvalidAddress());
|
||||||
|
|
||||||
|
/* Check the region attributes. */
|
||||||
|
const bool is_rw = perm == KMemoryPermission_UserReadWrite;
|
||||||
|
R_UNLESS( region_it->IsDerivedFrom(KMemoryRegionType_Dram), svc::ResultInvalidAddress());
|
||||||
|
R_UNLESS(!region_it->HasTypeAttribute(KMemoryRegionAttr_NoUserMap), svc::ResultInvalidAddress());
|
||||||
|
R_UNLESS(!region_it->HasTypeAttribute(KMemoryRegionAttr_UserReadOnly) || !is_rw, svc::ResultInvalidAddress());
|
||||||
|
|
||||||
|
/* Lock the table. */
|
||||||
|
KScopedLightLock lk(this->general_lock);
|
||||||
|
|
||||||
|
/* Select an address to map at. */
|
||||||
|
KProcessAddress addr = Null<KProcessAddress>;
|
||||||
|
const size_t phys_alignment = std::min(std::min(GetInteger(phys_addr) & -GetInteger(phys_addr), size & -size), MaxPhysicalMapAlignment);
|
||||||
|
for (s32 block_type = KPageTable::GetMaxBlockType(); block_type >= 0; block_type--) {
|
||||||
|
const size_t alignment = KPageTable::GetBlockSize(static_cast<KPageTable::BlockType>(block_type));
|
||||||
|
if (alignment > phys_alignment) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = this->FindFreeArea(region_start, region_num_pages, num_pages, alignment, 0, this->GetNumGuardPages());
|
||||||
|
if (addr != Null<KProcessAddress>) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
R_UNLESS(addr != Null<KProcessAddress>, svc::ResultOutOfMemory());
|
||||||
|
|
||||||
|
/* Check that we can map static here. */
|
||||||
|
MESOSPHERE_ASSERT(this->CanContain(addr, size, KMemoryState_Static));
|
||||||
|
MESOSPHERE_R_ASSERT(this->CheckMemoryState(addr, size, KMemoryState_All, KMemoryState_Free, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_None, KMemoryAttribute_None));
|
||||||
|
|
||||||
|
/* Create an update allocator. */
|
||||||
|
KMemoryBlockManagerUpdateAllocator allocator(this->memory_block_slab_manager);
|
||||||
|
R_TRY(allocator.GetResult());
|
||||||
|
|
||||||
|
/* We're going to perform an update, so create a helper. */
|
||||||
|
KScopedPageTableUpdater updater(this);
|
||||||
|
|
||||||
|
/* Perform mapping operation. */
|
||||||
|
const KPageProperties properties = { perm, false, false, false };
|
||||||
|
R_TRY(this->Operate(updater.GetPageList(), addr, num_pages, phys_addr, true, properties, OperationType_Map, false));
|
||||||
|
|
||||||
|
/* Update the blocks. */
|
||||||
|
this->memory_block_manager.Update(&allocator, addr, num_pages, KMemoryState_Static, perm, KMemoryAttribute_None);
|
||||||
|
|
||||||
|
/* We successfully mapped the pages. */
|
||||||
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) {
|
Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) {
|
||||||
MESOSPHERE_UNIMPLEMENTED();
|
/* Get the memory region. */
|
||||||
|
auto &tree = KMemoryLayout::GetPhysicalMemoryRegionTree();
|
||||||
|
auto it = tree.TryFindFirstDerivedRegion(region_type);
|
||||||
|
R_UNLESS(it != tree.end(), svc::ResultOutOfRange());
|
||||||
|
|
||||||
|
/* Map the region. */
|
||||||
|
R_TRY_CATCH(this->MapStatic(it->GetAddress(), it->GetSize(), perm)) {
|
||||||
|
R_CONVERT(svc::ResultInvalidAddress, svc::ResultOutOfRange())
|
||||||
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPageTableBase::MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
Result KPageTableBase::MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||||
|
|
|
@ -37,15 +37,19 @@ namespace ams::kern::svc {
|
||||||
|
|
||||||
/* Get the process from the object. */
|
/* Get the process from the object. */
|
||||||
KProcess *process = nullptr;
|
KProcess *process = nullptr;
|
||||||
if (obj->IsDerivedFrom(KProcess::GetStaticTypeObj())) {
|
if (KProcess *p = obj->DynamicCast<KProcess *>(); p != nullptr) {
|
||||||
/* The object is a process, so we can use it directly. */
|
/* The object is a process, so we can use it directly. */
|
||||||
process = reinterpret_cast<KProcess *>(obj.GetPointerUnsafe());
|
process = p;
|
||||||
} else if (obj->IsDerivedFrom(KThread::GetStaticTypeObj())) {
|
} else if (KThread *t = obj->DynamicCast<KThread *>(); t != nullptr) {
|
||||||
/* The object is a thread, so we want to use its parent. */
|
/* The object is a thread, so we want to use its parent. */
|
||||||
process = reinterpret_cast<KThread *>(obj.GetPointerUnsafe())->GetOwnerProcess();
|
process = reinterpret_cast<KThread *>(obj.GetPointerUnsafe())->GetOwnerProcess();
|
||||||
} else if (obj->IsDerivedFrom(KDebug::GetStaticTypeObj())) {
|
} else if (KDebug *d = obj->DynamicCast<KDebug *>(); d != nullptr) {
|
||||||
/* The object is a debug, so we want to use the process it's attached to. */
|
/* The object is a debug, so we want to use the process it's attached to. */
|
||||||
MESOSPHERE_UNIMPLEMENTED();
|
obj = d->GetProcess();
|
||||||
|
|
||||||
|
if (obj.IsNotNull()) {
|
||||||
|
process = static_cast<KProcess *>(obj.GetPointerUnsafe());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the target process exists. */
|
/* Make sure the target process exists. */
|
||||||
|
|
Loading…
Reference in a new issue