mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-23 04:12:02 +00:00
kern: SvcInvalidateProcessDataCache
This commit is contained in:
parent
46935fea80
commit
418de7b0dc
4 changed files with 91 additions and 2 deletions
|
@ -128,6 +128,10 @@ namespace ams::kern::arch::arm64 {
|
|||
return this->page_table.MakeAndOpenPageGroupContiguous(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||
}
|
||||
|
||||
Result InvalidateProcessDataCache(KProcessAddress address, size_t size) {
|
||||
return this->page_table.InvalidateProcessDataCache(address, size);
|
||||
}
|
||||
|
||||
Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) {
|
||||
return this->page_table.LockForDeviceAddressSpace(out, address, size, perm, is_aligned);
|
||||
}
|
||||
|
|
|
@ -313,6 +313,8 @@ namespace ams::kern {
|
|||
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
|
||||
Result MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
|
||||
|
||||
Result InvalidateProcessDataCache(KProcessAddress address, size_t size);
|
||||
|
||||
Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned);
|
||||
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
|
||||
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size);
|
||||
|
|
|
@ -1822,6 +1822,73 @@ namespace ams::kern {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_t size) {
|
||||
/* Check that the region is in range. */
|
||||
R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Lock the table. */
|
||||
KScopedLightLock lk(this->general_lock);
|
||||
|
||||
/* Check the memory state. */
|
||||
R_TRY(this->CheckMemoryStateContiguous(address, size, KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted, KMemoryPermission_UserReadWrite, KMemoryPermission_UserReadWrite, KMemoryAttribute_Uncached, KMemoryAttribute_None));
|
||||
|
||||
/* Get the impl. */
|
||||
auto &impl = this->GetImpl();
|
||||
|
||||
/* Begin traversal. */
|
||||
TraversalContext context;
|
||||
TraversalEntry next_entry;
|
||||
bool traverse_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), address);
|
||||
R_UNLESS(traverse_valid, svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Prepare tracking variables. */
|
||||
KPhysicalAddress cur_addr = next_entry.phys_addr;
|
||||
size_t cur_size = next_entry.block_size - (GetInteger(cur_addr) & (next_entry.block_size - 1));
|
||||
size_t tot_size = cur_size;
|
||||
|
||||
/* Iterate. */
|
||||
while (tot_size < size) {
|
||||
/* Continue the traversal. */
|
||||
traverse_valid = impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context));
|
||||
R_UNLESS(traverse_valid, svc::ResultInvalidCurrentMemory());
|
||||
|
||||
if (next_entry.phys_addr != (cur_addr + cur_size)) {
|
||||
/* Check that the pages are linearly mapped. */
|
||||
R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Invalidate the block. */
|
||||
if (cur_size > 0) {
|
||||
/* NOTE: Nintendo does not check the result of invalidation. */
|
||||
cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
|
||||
}
|
||||
|
||||
/* Advance. */
|
||||
cur_addr = next_entry.phys_addr;
|
||||
cur_size = next_entry.block_size;
|
||||
} else {
|
||||
cur_size += next_entry.block_size;
|
||||
}
|
||||
|
||||
tot_size += next_entry.block_size;
|
||||
}
|
||||
|
||||
/* Ensure we use the right size for the last block. */
|
||||
if (tot_size > size) {
|
||||
cur_size -= (tot_size - size);
|
||||
}
|
||||
|
||||
/* Check that the last block is linearly mapped. */
|
||||
R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Invalidate the last block. */
|
||||
if (cur_size > 0) {
|
||||
/* NOTE: Nintendo does not check the result of invalidation. */
|
||||
cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KPageTableBase::LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) {
|
||||
/* Lightly validate the range before doing anything else. */
|
||||
const size_t num_pages = size / PageSize;
|
||||
|
|
|
@ -73,6 +73,22 @@ namespace ams::kern::svc {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result InvalidateProcessDataCache(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||
/* Validate address/size. */
|
||||
R_UNLESS(size > 0, svc::ResultInvalidSize());
|
||||
R_UNLESS(address == static_cast<uintptr_t>(address), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(size == static_cast<size_t>(size), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Get the process from its handle. */
|
||||
KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject<KProcess>(process_handle);
|
||||
R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Invalidate the cache. */
|
||||
R_TRY(process->GetPageTable().InvalidateProcessDataCache(address, size));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result StoreProcessDataCache(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||
/* Validate address/size. */
|
||||
R_UNLESS(size > 0, svc::ResultInvalidSize());
|
||||
|
@ -140,7 +156,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result InvalidateProcessDataCache64(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcInvalidateProcessDataCache64 was called.");
|
||||
return InvalidateProcessDataCache(process_handle, address, size);
|
||||
}
|
||||
|
||||
Result StoreProcessDataCache64(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||
|
@ -162,7 +178,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result InvalidateProcessDataCache64From32(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcInvalidateProcessDataCache64From32 was called.");
|
||||
return InvalidateProcessDataCache(process_handle, address, size);
|
||||
}
|
||||
|
||||
Result StoreProcessDataCache64From32(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||
|
|
Loading…
Reference in a new issue