memory: flatten direct and batch mapping paths

This commit is contained in:
nmzik
2026-10-07 22:27:36 +04:00
parent c30ac7c904
commit 9c79d9d298
2 changed files with 178 additions and 97 deletions
+73 -97
View File
@@ -359,12 +359,6 @@ public:
EditUnlocked(start, size, [protection](Range* r) { r->protection = protection; });
}
void SetMemoryType(uint64_t start, uint64_t size, int memory_type) {
Common::LockGuard lock(m_mutex);
EditUnlocked(start, size, [memory_type](Range* r) { r->memory_type = memory_type; });
}
bool Query(uint64_t addr, int flags, Range* out) {
EXIT_IF(out == nullptr);
@@ -702,7 +696,7 @@ public:
bool Release(uint64_t start, size_t len, uint64_t* vaddr, uint64_t* size,
GpuAccessMode* gpu_mode);
bool Map(uint64_t vaddr, uint64_t phys_addr, size_t len, int prot, VirtualMemory::Mode mode,
GpuAccessMode gpu_mode);
GpuAccessMode gpu_mode, const char* name, int memory_type);
bool Unmap(uint64_t vaddr, uint64_t size, GpuAccessMode* gpu_mode,
uint64_t* host_vaddr_to_release = nullptr);
bool Find(uint64_t vaddr, uint64_t* base_addr, size_t* len, int* prot,
@@ -715,7 +709,6 @@ public:
void ProtectMapping(uint64_t vaddr, uint64_t size, int prot, VirtualMemory::Mode mode,
GpuAccessMode gpu_mode);
void SetVirtualRangeName(uint64_t vaddr, uint64_t len, const char* name);
void SetVirtualRangeMemoryType(uint64_t vaddr, uint64_t len, int memory_type);
[[nodiscard]] Common::Mutex& GetMutex() { return m_mutex; }
[[nodiscard]] const std::map<uint64_t, AllocatedBlock>& GetPhysicalBlocks() const {
@@ -1368,7 +1361,8 @@ bool PhysicalMemory::Release(uint64_t start, size_t len, uint64_t* vaddr, uint64
}
bool PhysicalMemory::Map(uint64_t vaddr, uint64_t phys_addr, size_t len, int prot,
VirtualMemory::Mode mode, GpuAccessMode gpu_mode) {
VirtualMemory::Mode mode, GpuAccessMode gpu_mode, const char* name,
int memory_type) {
Common::LockGuard lock(m_mutex);
if (len == 0 || UINT64_MAX - phys_addr < len) {
@@ -1413,6 +1407,8 @@ bool PhysicalMemory::Map(uint64_t vaddr, uint64_t phys_addr, size_t len, int pro
mapping.prot = prot;
mapping.mode = mode;
mapping.gpu_mode = gpu_mode;
mapping.memory_type = memory_type;
CopyVirtualRangeName(mapping.name, name);
m_mappings.push_back(mapping);
if (has_automatic) {
RemoveFreeRange(m_automatic_free, phys_addr, len);
@@ -2040,16 +2036,6 @@ void FlexibleMemory::SetVirtualRangeName(uint64_t vaddr, uint64_t len, const cha
}
}
void PhysicalMemory::SetVirtualRangeMemoryType(uint64_t vaddr, uint64_t len, int memory_type) {
Common::LockGuard lock(m_mutex);
for (auto& b: m_mappings) {
if (VirtualRangesOverlap(vaddr, len, b.map_vaddr, b.map_size)) {
b.memory_type = memory_type;
}
}
}
uint64_t FlexibleMemory::Available() {
Common::LockGuard lock(m_mutex);
@@ -2268,12 +2254,9 @@ static bool UnmapPooledBackingTransactional(const std::vector<PooledMemory::Mapp
return true;
}
int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot,
int flags, const char* name) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
// The ABI entry points and batch operations hold g_memory_operation_mutex.
static int MapFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags,
const char* name) {
EXIT_NOT_IMPLEMENTED(addr_in_out == nullptr);
constexpr size_t PAGE_SIZE = 0x4000;
@@ -2398,8 +2381,17 @@ int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t le
return OK;
}
int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot,
int flags, const char* name) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
return MapFlexibleMemory(addr_in_out, len, prot, flags, name);
}
int KYTY_SYSV_ABI KernelMapFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags) {
return KernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "");
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
return MapFlexibleMemory(addr_in_out, len, prot, flags, "");
}
int KYTY_SYSV_ABI KernelSetPrtAperture(int index, void* addr, size_t len) {
@@ -2607,11 +2599,8 @@ static int UnmapMemoryRange(uint64_t vaddr, size_t len) {
return OK;
}
int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
// The ABI entry point and batch operations hold g_memory_operation_mutex.
static int UnmapMemory(uint64_t vaddr, size_t len) {
LOGF("\t start = 0x%016" PRIx64 "\n"
"\t len = 0x%016" PRIx64 "\n",
vaddr, len);
@@ -2627,6 +2616,12 @@ int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len) {
return UnmapMemoryRange(vaddr, len);
}
int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
return UnmapMemory(vaddr, len);
}
size_t KYTY_SYSV_ABI KernelGetDirectMemorySize() {
PRINT_NAME();
@@ -2909,7 +2904,8 @@ static int ReleaseDirectMemoryInternal(int64_t start, size_t len) {
for (const auto& removed: metadata_unmapped) {
EXIT_IF(!g_physical_memory->Map(removed.map_vaddr, removed.start_addr,
removed.map_size, removed.prot, removed.mode,
removed.gpu_mode));
removed.gpu_mode, removed.name,
removed.memory_type));
}
restore_owner_aliases(owner_unmapped);
restore_gpu_aliases();
@@ -2980,12 +2976,10 @@ int KYTY_SYSV_ABI KernelCheckedReleaseDirectMemory(int64_t start, size_t len) {
return result == KERNEL_ERROR_EACCES ? KERNEL_ERROR_ENOENT : result;
}
int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int flags,
int64_t direct_memory_start, size_t alignment) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
// The ABI entry points and batch operations hold g_memory_operation_mutex.
static int MapDirectMemory(void** addr, size_t len, int prot, int flags,
int64_t direct_memory_start, size_t alignment, const char* name,
int type = -1) {
if (addr == nullptr) {
return KERNEL_ERROR_EFAULT;
}
@@ -3036,10 +3030,8 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
old.start_addr, old.mode));
}
EXIT_IF(!g_physical_memory->Map(old.map_vaddr, old.start_addr, old.map_size,
old.prot, old.mode, old.gpu_mode));
g_physical_memory->SetVirtualRangeName(old.map_vaddr, old.map_size, old.name);
g_physical_memory->SetVirtualRangeMemoryType(old.map_vaddr, old.map_size,
old.memory_type);
old.prot, old.mode, old.gpu_mode, old.name,
old.memory_type));
}
MapGpuRange(in_addr, len);
};
@@ -3168,7 +3160,11 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
return KERNEL_ERROR_ENOMEM;
}
if (!g_physical_memory->Map(out_addr, direct_memory_start, len, prot, mode, gpu_mode)) {
PhysicalMemory::AllocatedBlock mapped_block {};
g_physical_memory->Find(direct_memory_start, false, &mapped_block);
const int memory_type = type == -1 ? mapped_block.memory_type : type;
if (!g_physical_memory->Map(out_addr, direct_memory_start, len, prot, mode, gpu_mode, name,
memory_type)) {
LOGF_COLOR(Log::Color::Red, "\t [Fail]\n");
if (replaced_mappings.empty()) {
EXIT_IF(!g_guest_address_space->UnmapBacking(out_addr, len));
@@ -3178,18 +3174,16 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
return KERNEL_ERROR_EBUSY;
}
PhysicalMemory::AllocatedBlock mapped_block {};
g_physical_memory->Find(direct_memory_start, false, &mapped_block);
const bool published = !replaced_mappings.empty() || reserved_target
? g_virtual_ranges->ReplaceSpan(
out_addr, len, replaced_mappings.empty()
? VirtualRangeType::Reserved
: VirtualRangeType::Direct,
direct_memory_start,
prot, mapped_block.memory_type, VirtualRangeType::Direct, "")
prot, memory_type, VirtualRangeType::Direct, name)
: g_virtual_ranges->Add(out_addr, len, direct_memory_start, prot,
mapped_block.memory_type,
VirtualRangeType::Direct, "");
memory_type,
VirtualRangeType::Direct, name);
if (!published) {
GpuAccessMode rollback_gpu_mode = GpuAccessMode::NoAccess;
EXIT_IF(!g_physical_memory->Unmap(out_addr, len, &rollback_gpu_mode));
@@ -3212,22 +3206,18 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
return OK;
}
int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int flags,
int64_t direct_memory_start, size_t alignment) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
return MapDirectMemory(addr, len, prot, flags, direct_memory_start, alignment, "");
}
int KYTY_SYSV_ABI KernelMapDirectMemory2(void** addr, size_t len, int type, int prot, int flags,
int64_t direct_memory_start, size_t alignment) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
LOGF("\t type = %d\n", type);
auto ret = KernelMapDirectMemory(addr, len, prot, flags, direct_memory_start, alignment);
if (ret == OK && addr != nullptr && *addr != nullptr) {
const auto out_addr = reinterpret_cast<uint64_t>(*addr);
g_physical_memory->SetVirtualRangeMemoryType(out_addr, len, type);
g_virtual_ranges->SetMemoryType(out_addr, len, type);
}
return ret;
return MapDirectMemory(addr, len, prot, flags, direct_memory_start, alignment, "", type);
}
int MapAutomaticMemory(uint64_t vaddr, size_t size, int type, int prot) {
@@ -3246,11 +3236,11 @@ int MapAutomaticMemory(uint64_t vaddr, size_t size, int type, int prot) {
uint64_t mapped = 0;
for (const auto& [offset, length]: ranges) {
void* address = reinterpret_cast<void*>(vaddr + mapped);
const int result = KernelMapDirectMemory2(&address, length, type, prot, 0x10,
static_cast<int64_t>(offset), page_size);
const int result = MapDirectMemory(&address, length, prot, 0x10,
static_cast<int64_t>(offset), page_size, "", type);
if (result != OK) {
if (mapped != 0) {
EXIT_IF(KernelMunmap(vaddr, mapped) != OK);
EXIT_IF(UnmapMemory(vaddr, mapped) != OK);
}
g_physical_memory->RestoreAutomatic(ranges);
return result;
@@ -3277,13 +3267,7 @@ int KYTY_SYSV_ABI KernelMapNamedDirectMemory(void** addr, size_t len, int prot,
return KERNEL_ERROR_ENAMETOOLONG;
}
auto ret = KernelMapDirectMemory(addr, len, prot, flags, direct_memory_start, alignment);
if (ret == OK && addr != nullptr) {
g_physical_memory->SetVirtualRangeName(reinterpret_cast<uint64_t>(*addr), len, name);
g_virtual_ranges->Rename(reinterpret_cast<uint64_t>(*addr), len, name);
}
return ret;
return MapDirectMemory(addr, len, prot, flags, direct_memory_start, alignment, name);
}
int KYTY_SYSV_ABI KernelIsAddressSanitizerEnabled() {
@@ -3389,7 +3373,8 @@ static bool ReplaceFixedRangeWithReserved(uint64_t start, uint64_t size) {
if (chunk.backend_unmapped) {
backend_restored = g_physical_memory->Map(
chunk.range.start, chunk.range.offset, chunk.range.size,
chunk.range.protection, chunk.mode, chunk.gpu_mode);
chunk.range.protection, chunk.mode, chunk.gpu_mode, chunk.range.name,
chunk.range.memory_type);
}
} else if (chunk.range.type == VirtualRangeType::Flexible && chunk.backend_unmapped) {
host_restored = backend_restored =
@@ -3905,11 +3890,8 @@ bool FreeGuestMemory(uint64_t vaddr, uint64_t size) {
return FreeGuestMemoryOwner(vaddr, mapped_size);
}
int KYTY_SYSV_ABI KernelMprotect(const void* addr, size_t len, int prot) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
// The ABI entry points and batch operations hold g_memory_operation_mutex.
static int ProtectMemory(const void* addr, size_t len, int prot) {
auto vaddr = reinterpret_cast<uint64_t>(addr);
LOGF("\t addr = 0x%016" PRIx64 "\n"
@@ -3967,19 +3949,17 @@ int KYTY_SYSV_ABI KernelMprotect(const void* addr, size_t len, int prot) {
return OK;
}
int KYTY_SYSV_ABI KernelMprotect(const void* addr, size_t len, int prot) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
return ProtectMemory(addr, len, prot);
}
int KYTY_SYSV_ABI KernelMtypeprotect(const void* addr, size_t len, int type, int prot) {
PRINT_NAME();
std::lock_guard<std::recursive_mutex> memory_operation_lock(g_memory_operation_mutex);
LOGF("\t addr = 0x%016" PRIx64 "\n"
"\t len = 0x%016" PRIx64 "\n"
"\t type = 0x%08" PRIx32 "\n"
"\t prot = 0x%08" PRIx32 "\n",
reinterpret_cast<uint64_t>(addr), static_cast<uint64_t>(len), static_cast<uint32_t>(type),
static_cast<uint32_t>(prot));
return KernelMprotect(addr, len, prot);
LOGF("\t type = %d\n", type);
return ProtectMemory(addr, len, prot);
}
int KYTY_SYSV_ABI KernelBatchMap2(KernelBatchMapEntry* entries, int num_entries,
@@ -4026,23 +4006,19 @@ int KYTY_SYSV_ABI KernelBatchMap2(KernelBatchMapEntry* entries, int num_entries,
int result = OK;
switch (entry->operation) {
case MAP_OP_MAP_DIRECT:
result = KernelMapNamedDirectMemory(&entry->start, entry->length, entry->protection,
flags, static_cast<int64_t>(entry->offset), 0,
"anon");
result = MapDirectMemory(&entry->start, entry->length, entry->protection, flags,
static_cast<int64_t>(entry->offset), 0, "anon");
break;
case MAP_OP_UNMAP:
result = KernelMunmap(reinterpret_cast<uint64_t>(entry->start), entry->length);
result = UnmapMemory(reinterpret_cast<uint64_t>(entry->start), entry->length);
break;
case MAP_OP_PROTECT:
result = KernelMprotect(entry->start, entry->length, entry->protection);
case MAP_OP_TYPE_PROTECT:
result = ProtectMemory(entry->start, entry->length, entry->protection);
break;
case MAP_OP_MAP_FLEXIBLE:
result = KernelMapNamedFlexibleMemory(&entry->start, entry->length,
entry->protection, flags, "anon");
break;
case MAP_OP_TYPE_PROTECT:
result =
KernelMtypeprotect(entry->start, entry->length, entry->type, entry->protection);
result = MapFlexibleMemory(&entry->start, entry->length, entry->protection, flags,
"anon");
break;
default: result = KERNEL_ERROR_EINVAL; break;
}