kern: update for new device map semantics

This commit is contained in:
Michael Scire 2022-10-11 22:22:11 -07:00 committed by SciresM
parent 947fdcf6f6
commit 5ee7d8a5ed
14 changed files with 115 additions and 58 deletions

View file

@ -61,10 +61,21 @@ namespace ams::kern {
R_RETURN(m_table.Detach(device_name));
}
Result KDeviceAddressSpace::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) {
Result KDeviceAddressSpace::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option, bool is_aligned) {
/* Check that the address falls within the space. */
R_UNLESS((m_space_address <= device_address && device_address + size - 1 <= m_space_address + m_space_size - 1), svc::ResultInvalidCurrentMemory());
/* Decode the option. */
const util::BitPack32 option_pack = { option };
const auto device_perm = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Permission>();
const auto flags = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Flags>();
const auto reserved = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Reserved>();
/* Validate the option. */
/* TODO: It is likely that this check for flags == none is only on NX board. */
R_UNLESS(flags == ams::svc::MapDeviceAddressSpaceFlag_None, svc::ResultInvalidEnumValue());
R_UNLESS(reserved == 0, svc::ResultInvalidEnumValue());
/* Lock the address space. */
KScopedLightLock lk(m_lock);
@ -72,15 +83,21 @@ namespace ams::kern {
KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
/* Lock the pages. */
R_TRY(page_table->LockForMapDeviceAddressSpace(process_address, size, ConvertToKMemoryPermission(device_perm), is_aligned));
bool is_io{};
R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size, ConvertToKMemoryPermission(device_perm), is_aligned, true));
/* Ensure that if we fail, we don't keep unmapped pages locked. */
ON_RESULT_FAILURE { MESOSPHERE_R_ABORT_UNLESS(page_table->UnlockForDeviceAddressSpace(process_address, size)); };
/* Check that the io status is allowable. */
if (is_io) {
R_UNLESS((flags & ams::svc::MapDeviceAddressSpaceFlag_NotIoRegister) == 0, svc::ResultInvalidCombination());
}
/* Map the pages. */
{
/* Perform the mapping. */
R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, is_aligned));
R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, is_aligned, is_io));
/* Ensure that we unmap the pages if we fail to update the protections. */
/* NOTE: Nintendo does not check the result of this unmap call. */
@ -105,7 +122,7 @@ namespace ams::kern {
KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
/* Lock the pages. */
R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size));
R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true));
/* Unmap the pages. */
{