mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-23 12:22:08 +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);
|
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) {
|
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);
|
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 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 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 LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned);
|
||||||
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
|
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
|
||||||
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size);
|
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size);
|
||||||
|
|
|
@ -1822,6 +1822,73 @@ namespace ams::kern {
|
||||||
return ResultSuccess();
|
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) {
|
Result KPageTableBase::LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) {
|
||||||
/* Lightly validate the range before doing anything else. */
|
/* Lightly validate the range before doing anything else. */
|
||||||
const size_t num_pages = size / PageSize;
|
const size_t num_pages = size / PageSize;
|
||||||
|
|
|
@ -73,6 +73,22 @@ namespace ams::kern::svc {
|
||||||
return ResultSuccess();
|
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) {
|
Result StoreProcessDataCache(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||||
/* Validate address/size. */
|
/* Validate address/size. */
|
||||||
R_UNLESS(size > 0, svc::ResultInvalidSize());
|
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) {
|
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) {
|
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) {
|
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) {
|
Result StoreProcessDataCache64From32(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {
|
||||||
|
|
Loading…
Reference in a new issue