mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
kern: track heap in KPageTableBase::MemoryRange
This commit is contained in:
parent
a7300b0fa4
commit
ed9e60acb9
4 changed files with 50 additions and 28 deletions
|
@ -57,10 +57,25 @@ namespace ams::kern {
|
||||||
using TraversalEntry = KPageTableImpl::TraversalEntry;
|
using TraversalEntry = KPageTableImpl::TraversalEntry;
|
||||||
using TraversalContext = KPageTableImpl::TraversalContext;
|
using TraversalContext = KPageTableImpl::TraversalContext;
|
||||||
|
|
||||||
struct MemoryRange {
|
class MemoryRange {
|
||||||
KPhysicalAddress address;
|
private:
|
||||||
size_t size;
|
KPhysicalAddress m_address;
|
||||||
|
size_t m_size;
|
||||||
|
bool m_heap;
|
||||||
|
public:
|
||||||
|
constexpr MemoryRange() : m_address(Null<KPhysicalAddress>), m_size(0), m_heap(false) { /* ... */ }
|
||||||
|
|
||||||
|
void Set(KPhysicalAddress address, size_t size, bool heap) {
|
||||||
|
m_address = address;
|
||||||
|
m_size = size;
|
||||||
|
m_heap = heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr KPhysicalAddress GetAddress() const { return m_address; }
|
||||||
|
constexpr size_t GetSize() const { return m_size; }
|
||||||
|
constexpr bool IsHeap() const { return m_heap; }
|
||||||
|
|
||||||
|
void Open();
|
||||||
void Close();
|
void Close();
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1133,17 +1133,17 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
size_t cur_size;
|
size_t cur_size;
|
||||||
{
|
{
|
||||||
/* Get the current contiguous range. */
|
/* Get the current contiguous range. */
|
||||||
KPageTableBase::MemoryRange contig_range = { .address = Null<KPhysicalAddress>, .size = 0 };
|
KPageTableBase::MemoryRange contig_range;
|
||||||
R_TRY(page_table->OpenMemoryRangeForMapDeviceAddressSpace(std::addressof(contig_range), process_address + mapped_size, size - mapped_size, ConvertToKMemoryPermission(device_perm), is_aligned));
|
R_TRY(page_table->OpenMemoryRangeForMapDeviceAddressSpace(std::addressof(contig_range), process_address + mapped_size, size - mapped_size, ConvertToKMemoryPermission(device_perm), is_aligned));
|
||||||
|
|
||||||
/* Ensure we close the range when we're done. */
|
/* Ensure we close the range when we're done. */
|
||||||
ON_SCOPE_EXIT { contig_range.Close(); };
|
ON_SCOPE_EXIT { contig_range.Close(); };
|
||||||
|
|
||||||
/* Get the current size. */
|
/* Get the current size. */
|
||||||
cur_size = contig_range.size;
|
cur_size = contig_range.GetSize();
|
||||||
|
|
||||||
/* Map the device page. */
|
/* Map the device page. */
|
||||||
R_TRY(this->MapDevicePage(contig_range.address, contig_range.size, cur_addr, device_perm));
|
R_TRY(this->MapDevicePage(contig_range.GetAddress(), cur_size, cur_addr, device_perm));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
|
@ -1288,7 +1288,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0);
|
MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0);
|
||||||
|
|
||||||
/* We need to traverse the ranges that make up our mapping, to make sure they're all good. Start by getting a contiguous range. */
|
/* We need to traverse the ranges that make up our mapping, to make sure they're all good. Start by getting a contiguous range. */
|
||||||
KPageTableBase::MemoryRange contig_range = { .address = Null<KPhysicalAddress>, .size = 0 };
|
KPageTableBase::MemoryRange contig_range;
|
||||||
if (R_FAILED(page_table->OpenMemoryRangeForUnmapDeviceAddressSpace(std::addressof(contig_range), process_address, size))) {
|
if (R_FAILED(page_table->OpenMemoryRangeForUnmapDeviceAddressSpace(std::addressof(contig_range), process_address, size))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1300,8 +1300,8 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
/* Walk the directory. */
|
/* Walk the directory. */
|
||||||
KProcessAddress cur_process_address = process_address;
|
KProcessAddress cur_process_address = process_address;
|
||||||
size_t remaining_size = size;
|
size_t remaining_size = size;
|
||||||
KPhysicalAddress cur_phys_address = contig_range.address;
|
KPhysicalAddress cur_phys_address = contig_range.GetAddress();
|
||||||
size_t remaining_in_range = contig_range.size;
|
size_t remaining_in_range = contig_range.GetSize();
|
||||||
bool first = true;
|
bool first = true;
|
||||||
u32 first_attr = 0;
|
u32 first_attr = 0;
|
||||||
while (remaining_size > 0) {
|
while (remaining_size > 0) {
|
||||||
|
@ -1347,8 +1347,8 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
}
|
}
|
||||||
range_open = true;
|
range_open = true;
|
||||||
|
|
||||||
cur_phys_address = contig_range.address;
|
cur_phys_address = contig_range.GetAddress();
|
||||||
remaining_in_range = contig_range.size;
|
remaining_in_range = contig_range.GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the physical address is expected. */
|
/* Check that the physical address is expected. */
|
||||||
|
@ -1390,8 +1390,8 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
}
|
}
|
||||||
range_open = true;
|
range_open = true;
|
||||||
|
|
||||||
cur_phys_address = contig_range.address;
|
cur_phys_address = contig_range.GetAddress();
|
||||||
remaining_in_range = contig_range.size;
|
remaining_in_range = contig_range.GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the physical address is expected, and there's enough in the range. */
|
/* Check that the physical address is expected, and there's enough in the range. */
|
||||||
|
|
|
@ -74,8 +74,18 @@ namespace ams::kern {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KPageTableBase::MemoryRange::Open() {
|
||||||
|
/* If the range contains heap pages, open them. */
|
||||||
|
if (this->IsHeap()) {
|
||||||
|
Kernel::GetMemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KPageTableBase::MemoryRange::Close() {
|
void KPageTableBase::MemoryRange::Close() {
|
||||||
Kernel::GetMemoryManager().Close(address, size / PageSize);
|
/* If the range contains heap pages, close them. */
|
||||||
|
if (this->IsHeap()) {
|
||||||
|
Kernel::GetMemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) {
|
Result KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||||
|
@ -1504,16 +1514,13 @@ namespace ams::kern {
|
||||||
|
|
||||||
/* Check that the memory is contiguous (modulo the reference count bit). */
|
/* Check that the memory is contiguous (modulo the reference count bit). */
|
||||||
const u32 test_state_mask = state_mask | KMemoryState_FlagReferenceCounted;
|
const u32 test_state_mask = state_mask | KMemoryState_FlagReferenceCounted;
|
||||||
if (R_FAILED(this->CheckMemoryStateContiguous(address, size, test_state_mask, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr))) {
|
const bool is_heap = R_SUCCEEDED(this->CheckMemoryStateContiguous(address, size, test_state_mask, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr));
|
||||||
|
if (!is_heap) {
|
||||||
R_TRY(this->CheckMemoryStateContiguous(address, size, test_state_mask, state, perm_mask, perm, attr_mask, attr));
|
R_TRY(this->CheckMemoryStateContiguous(address, size, test_state_mask, state, perm_mask, perm, attr_mask, attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The memory is contiguous, so set the output range. */
|
/* The memory is contiguous, so set the output range. */
|
||||||
*out = {
|
out->Set(phys_address, size, is_heap);
|
||||||
.address = phys_address,
|
|
||||||
.size = size,
|
|
||||||
};
|
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2932,7 +2939,7 @@ namespace ams::kern {
|
||||||
KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None));
|
KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None));
|
||||||
|
|
||||||
/* We got the range, so open it. */
|
/* We got the range, so open it. */
|
||||||
Kernel::GetMemoryManager().Open(out->address, out->size / PageSize);
|
out->Open();
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
@ -2949,7 +2956,7 @@ namespace ams::kern {
|
||||||
KMemoryAttribute_DeviceShared | KMemoryAttribute_Locked, KMemoryAttribute_DeviceShared));
|
KMemoryAttribute_DeviceShared | KMemoryAttribute_Locked, KMemoryAttribute_DeviceShared));
|
||||||
|
|
||||||
/* We got the range, so open it. */
|
/* We got the range, so open it. */
|
||||||
Kernel::GetMemoryManager().Open(out->address, out->size / PageSize);
|
out->Open();
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
@ -3020,7 +3027,7 @@ namespace ams::kern {
|
||||||
KMemoryAttribute_Uncached, KMemoryAttribute_None));
|
KMemoryAttribute_Uncached, KMemoryAttribute_None));
|
||||||
|
|
||||||
/* We got the range, so open it. */
|
/* We got the range, so open it. */
|
||||||
Kernel::GetMemoryManager().Open(out->address, out->size / PageSize);
|
out->Open();
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,15 +36,15 @@ namespace ams::kern::svc {
|
||||||
size_t remaining = size;
|
size_t remaining = size;
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
/* Get a contiguous range to operate on. */
|
/* Get a contiguous range to operate on. */
|
||||||
KPageTableBase::MemoryRange contig_range = { .address = Null<KPhysicalAddress>, .size = 0 };
|
KPageTableBase::MemoryRange contig_range;
|
||||||
R_TRY(page_table.OpenMemoryRangeForProcessCacheOperation(std::addressof(contig_range), cur_address, aligned_end - cur_address));
|
R_TRY(page_table.OpenMemoryRangeForProcessCacheOperation(std::addressof(contig_range), cur_address, aligned_end - cur_address));
|
||||||
|
|
||||||
/* Close the range when we're done operating on it. */
|
/* Close the range when we're done operating on it. */
|
||||||
ON_SCOPE_EXIT { contig_range.Close(); };
|
ON_SCOPE_EXIT { contig_range.Close(); };
|
||||||
|
|
||||||
/* Adjust to remain within range. */
|
/* Adjust to remain within range. */
|
||||||
KVirtualAddress operate_address = KMemoryLayout::GetLinearVirtualAddress(contig_range.address);
|
KVirtualAddress operate_address = KMemoryLayout::GetLinearVirtualAddress(contig_range.GetAddress());
|
||||||
size_t operate_size = contig_range.size;
|
size_t operate_size = contig_range.GetSize();
|
||||||
if (cur_address < address) {
|
if (cur_address < address) {
|
||||||
operate_address += (address - cur_address);
|
operate_address += (address - cur_address);
|
||||||
operate_size -= (address - cur_address);
|
operate_size -= (address - cur_address);
|
||||||
|
@ -57,7 +57,7 @@ namespace ams::kern::svc {
|
||||||
operation.Operate(GetVoidPointer(operate_address), operate_size);
|
operation.Operate(GetVoidPointer(operate_address), operate_size);
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
cur_address += contig_range.size;
|
cur_address += contig_range.GetSize();
|
||||||
remaining -= operate_size;
|
remaining -= operate_size;
|
||||||
}
|
}
|
||||||
MESOSPHERE_ASSERT(remaining == 0);
|
MESOSPHERE_ASSERT(remaining == 0);
|
||||||
|
|
Loading…
Reference in a new issue