kern: implement SvcSetMemoryAttribute

This commit is contained in:
Michael Scire 2020-07-22 18:46:28 -07:00 committed by SciresM
parent 185baa7c4d
commit ab96255a5d
5 changed files with 67 additions and 2 deletions

View file

@ -44,6 +44,10 @@ namespace ams::kern::arch::arm64 {
return this->page_table.SetProcessMemoryPermission(addr, size, perm); return this->page_table.SetProcessMemoryPermission(addr, size, perm);
} }
Result SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mask, u32 attr) {
return this->page_table.SetMemoryAttribute(addr, size, mask, attr);
}
Result SetHeapSize(KProcessAddress *out, size_t size) { Result SetHeapSize(KProcessAddress *out, size_t size) {
return this->page_table.SetHeapSize(out, size); return this->page_table.SetHeapSize(out, size);
} }

View file

@ -174,6 +174,8 @@ namespace ams::kern {
KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached, KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached,
KMemoryAttribute_AnyLocked = 0x80, KMemoryAttribute_AnyLocked = 0x80,
KMemoryAttribute_SetMask = KMemoryAttribute_Uncached,
}; };
struct KMemoryInfo { struct KMemoryInfo {

View file

@ -271,6 +271,7 @@ namespace ams::kern {
Result SetMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm); Result SetMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
Result SetProcessMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm); Result SetProcessMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
Result SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mask, u32 attr);
Result SetHeapSize(KProcessAddress *out, size_t size); Result SetHeapSize(KProcessAddress *out, size_t size);
Result SetMaxHeapSize(size_t size); Result SetMaxHeapSize(size_t size);
Result QueryInfo(KMemoryInfo *out_info, ams::svc::PageInfo *out_page_info, KProcessAddress addr) const; Result QueryInfo(KMemoryInfo *out_info, ams::svc::PageInfo *out_page_info, KProcessAddress addr) const;

View file

@ -1080,6 +1080,44 @@ namespace ams::kern {
return ResultSuccess(); return ResultSuccess();
} }
Result KPageTableBase::SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mask, u32 attr) {
const size_t num_pages = size / PageSize;
MESOSPHERE_ASSERT((mask | KMemoryAttribute_SetMask) == KMemoryAttribute_SetMask);
/* Lock the table. */
KScopedLightLock lk(this->general_lock);
/* Verify we can change the memory attribute. */
KMemoryState old_state;
KMemoryPermission old_perm;
KMemoryAttribute old_attr;
constexpr u32 AttributeTestMask = ~(KMemoryAttribute_SetMask | KMemoryAttribute_DeviceShared);
R_TRY(this->CheckMemoryState(std::addressof(old_state), std::addressof(old_perm), std::addressof(old_attr),
addr, size,
KMemoryState_FlagCanChangeAttribute, KMemoryState_FlagCanChangeAttribute,
KMemoryPermission_None, KMemoryPermission_None,
AttributeTestMask, KMemoryAttribute_None, ~AttributeTestMask));
/* 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);
/* Determine the new attribute. */
const KMemoryAttribute new_attr = static_cast<KMemoryAttribute>(((old_attr & ~mask) | (attr & mask)));
/* Perform operation. */
const KPageProperties properties = { old_perm, false, (new_attr & KMemoryAttribute_Uncached) != 0, false };
R_TRY(this->Operate(updater.GetPageList(), addr, num_pages, Null<KPhysicalAddress>, false, properties, OperationType_ChangePermissionsAndRefresh, false));
/* Update the blocks. */
this->memory_block_manager.Update(&allocator, addr, num_pages, old_state, old_perm, new_attr);
return ResultSuccess();
}
Result KPageTableBase::SetHeapSize(KProcessAddress *out, size_t size) { Result KPageTableBase::SetHeapSize(KProcessAddress *out, size_t size) {
/* Lock the physical memory mutex. */ /* Lock the physical memory mutex. */
KScopedLightLock map_phys_mem_lk(this->map_physical_memory_lock); KScopedLightLock map_phys_mem_lk(this->map_physical_memory_lock);

View file

@ -21,6 +21,26 @@ namespace ams::kern::svc {
namespace { namespace {
Result SetMemoryAttribute(uintptr_t address, size_t size, uint32_t mask, uint32_t attr) {
/* Validate address / size. */
R_UNLESS(util::IsAligned(address, PageSize), svc::ResultInvalidAddress());
R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize());
R_UNLESS(size > 0, svc::ResultInvalidSize());
R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory());
/* Validate the attribute and mask. */
constexpr u32 SupportedMask = ams::svc::MemoryAttribute_Uncached;
R_UNLESS((mask | attr) == mask, svc::ResultInvalidCombination());
R_UNLESS((mask | attr | SupportedMask) == SupportedMask, svc::ResultInvalidCombination());
/* Validate that the region is in range for the current process. */
auto &page_table = GetCurrentProcess().GetPageTable();
R_UNLESS(page_table.Contains(address, size), svc::ResultInvalidCurrentMemory());
/* Set the memory attribute. */
return page_table.SetMemoryAttribute(address, size, mask, attr);
}
Result MapMemory(uintptr_t dst_address, uintptr_t src_address, size_t size) { Result MapMemory(uintptr_t dst_address, uintptr_t src_address, size_t size) {
/* Validate that addresses are page aligned. */ /* Validate that addresses are page aligned. */
R_UNLESS(util::IsAligned(dst_address, PageSize), svc::ResultInvalidAddress()); R_UNLESS(util::IsAligned(dst_address, PageSize), svc::ResultInvalidAddress());
@ -81,7 +101,7 @@ namespace ams::kern::svc {
} }
Result SetMemoryAttribute64(ams::svc::Address address, ams::svc::Size size, uint32_t mask, uint32_t attr) { Result SetMemoryAttribute64(ams::svc::Address address, ams::svc::Size size, uint32_t mask, uint32_t attr) {
MESOSPHERE_PANIC("Stubbed SvcSetMemoryAttribute64 was called."); return SetMemoryAttribute(address, size, mask, attr);
} }
Result MapMemory64(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) { Result MapMemory64(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) {
@ -99,7 +119,7 @@ namespace ams::kern::svc {
} }
Result SetMemoryAttribute64From32(ams::svc::Address address, ams::svc::Size size, uint32_t mask, uint32_t attr) { Result SetMemoryAttribute64From32(ams::svc::Address address, ams::svc::Size size, uint32_t mask, uint32_t attr) {
MESOSPHERE_PANIC("Stubbed SvcSetMemoryAttribute64From32 was called."); return SetMemoryAttribute(address, size, mask, attr);
} }
Result MapMemory64From32(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) { Result MapMemory64From32(ams::svc::Address dst_address, ams::svc::Address src_address, ams::svc::Size size) {