summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/file_sys/program_metadata.cpp4
-rw-r--r--src/core/file_sys/program_metadata.h6
-rw-r--r--src/core/hle/kernel/process.cpp8
-rw-r--r--src/core/hle/kernel/process.h12
-rw-r--r--src/core/hle/kernel/vm_manager.cpp154
-rw-r--r--src/core/hle/kernel/vm_manager.h84
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp11
-rw-r--r--src/core/loader/elf.cpp8
-rw-r--r--src/core/loader/nro.cpp5
-rw-r--r--src/core/loader/nso.cpp5
10 files changed, 259 insertions, 38 deletions
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index 02319ce0f..8903ed1d3 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -83,10 +83,12 @@ void ProgramMetadata::Print() const {
auto address_space = "Unknown";
switch (npdm_header.address_space_type) {
- case ProgramAddressSpaceType::Is64Bit:
+ case ProgramAddressSpaceType::Is36Bit:
+ case ProgramAddressSpaceType::Is39Bit:
address_space = "64-bit";
break;
case ProgramAddressSpaceType::Is32Bit:
+ case ProgramAddressSpaceType::Is32BitNoMap:
address_space = "32-bit";
break;
}
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index 1143e36c4..e4470d6f0 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -17,8 +17,10 @@ enum class ResultStatus : u16;
namespace FileSys {
enum class ProgramAddressSpaceType : u8 {
- Is64Bit = 1,
- Is32Bit = 2,
+ Is32Bit = 0,
+ Is36Bit = 1,
+ Is32BitNoMap = 2,
+ Is39Bit = 3,
};
enum class ProgramFilePermission : u64 {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 121f741fd..f337f626f 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -8,6 +8,7 @@
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/core.h"
+#include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
@@ -34,14 +35,21 @@ SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) {
process->name = std::move(name);
process->flags.raw = 0;
process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
+ process->resource_limit = kernel.ResourceLimitForCategory(ResourceLimitCategory::APPLICATION);
process->status = ProcessStatus::Created;
process->program_id = 0;
process->process_id = kernel.CreateNewProcessID();
+ process->svc_access_mask.set();
kernel.AppendNewProcess(process);
return process;
}
+void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
+ program_id = metadata.GetTitleID();
+ vm_manager.Reset(metadata.GetAddressSpaceType());
+}
+
void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) {
for (std::size_t i = 0; i < len; ++i) {
u32 descriptor = kernel_caps[i];
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 04d74e572..adb03c228 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -17,6 +17,10 @@
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/vm_manager.h"
+namespace FileSys {
+class ProgramMetadata;
+}
+
namespace Kernel {
class KernelCore;
@@ -141,6 +145,14 @@ public:
return process_id;
}
+ /**
+ * Loads process-specifics configuration info with metadata provided
+ * by an executable.
+ *
+ * @param metadata The provided metadata to load process specific info.
+ */
+ void LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
+
/// Title ID corresponding to the process
u64 program_id;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 608cbd57b..337f17b7b 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -9,6 +9,7 @@
#include "common/logging/log.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
+#include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/vm_manager.h"
#include "core/memory.h"
@@ -54,25 +55,24 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
}
VMManager::VMManager() {
- Reset();
+ // Default to assuming a 39-bit address space. This way we have a sane
+ // starting point with executables that don't provide metadata.
+ Reset(FileSys::ProgramAddressSpaceType::Is39Bit);
}
VMManager::~VMManager() {
- Reset();
+ Reset(FileSys::ProgramAddressSpaceType::Is39Bit);
}
-void VMManager::Reset() {
- vma_map.clear();
+void VMManager::Reset(FileSys::ProgramAddressSpaceType type) {
+ Clear();
+ InitializeMemoryRegionRanges(type);
// Initialize the map with a single free region covering the entire managed space.
VirtualMemoryArea initial_vma;
initial_vma.size = MAX_ADDRESS;
vma_map.emplace(initial_vma.base, initial_vma);
- page_table.pointers.fill(nullptr);
- page_table.special_regions.clear();
- page_table.attributes.fill(Memory::PageType::Unmapped);
-
UpdatePageTableForVMA(initial_vma);
}
@@ -382,6 +382,84 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
}
}
+void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type) {
+ u64 map_region_size = 0;
+ u64 heap_region_size = 0;
+ u64 new_map_region_size = 0;
+ u64 tls_io_region_size = 0;
+
+ switch (type) {
+ case FileSys::ProgramAddressSpaceType::Is32Bit:
+ address_space_width = 32;
+ code_region_base = 0x200000;
+ code_region_end = code_region_base + 0x3FE00000;
+ map_region_size = 0x40000000;
+ heap_region_size = 0x40000000;
+ break;
+ case FileSys::ProgramAddressSpaceType::Is36Bit:
+ address_space_width = 36;
+ code_region_base = 0x8000000;
+ code_region_end = code_region_base + 0x78000000;
+ map_region_size = 0x180000000;
+ heap_region_size = 0x180000000;
+ break;
+ case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
+ address_space_width = 32;
+ code_region_base = 0x200000;
+ code_region_end = code_region_base + 0x3FE00000;
+ map_region_size = 0;
+ heap_region_size = 0x80000000;
+ break;
+ case FileSys::ProgramAddressSpaceType::Is39Bit:
+ address_space_width = 39;
+ code_region_base = 0x8000000;
+ code_region_end = code_region_base + 0x80000000;
+ map_region_size = 0x1000000000;
+ heap_region_size = 0x180000000;
+ new_map_region_size = 0x80000000;
+ tls_io_region_size = 0x1000000000;
+ break;
+ default:
+ UNREACHABLE_MSG("Invalid address space type specified: {}", static_cast<u32>(type));
+ return;
+ }
+
+ address_space_base = 0;
+ address_space_end = 1ULL << address_space_width;
+
+ map_region_base = code_region_end;
+ map_region_end = map_region_base + map_region_size;
+
+ heap_region_base = map_region_end;
+ heap_region_end = heap_region_base + heap_region_size;
+
+ new_map_region_base = heap_region_end;
+ new_map_region_end = new_map_region_base + new_map_region_size;
+
+ tls_io_region_base = new_map_region_end;
+ tls_io_region_end = tls_io_region_base + tls_io_region_size;
+
+ if (new_map_region_size == 0) {
+ new_map_region_base = address_space_base;
+ new_map_region_end = address_space_end;
+ }
+}
+
+void VMManager::Clear() {
+ ClearVMAMap();
+ ClearPageTable();
+}
+
+void VMManager::ClearVMAMap() {
+ vma_map.clear();
+}
+
+void VMManager::ClearPageTable() {
+ page_table.pointers.fill(nullptr);
+ page_table.special_regions.clear();
+ page_table.attributes.fill(Memory::PageType::Unmapped);
+}
+
u64 VMManager::GetTotalMemoryUsage() const {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0xF8000000;
@@ -402,4 +480,64 @@ u64 VMManager::GetAddressSpaceSize() const {
return MAX_ADDRESS;
}
+VAddr VMManager::GetCodeRegionBaseAddress() const {
+ return code_region_base;
+}
+
+VAddr VMManager::GetCodeRegionEndAddress() const {
+ return code_region_end;
+}
+
+u64 VMManager::GetCodeRegionSize() const {
+ return code_region_end - code_region_base;
+}
+
+VAddr VMManager::GetHeapRegionBaseAddress() const {
+ return heap_region_base;
+}
+
+VAddr VMManager::GetHeapRegionEndAddress() const {
+ return heap_region_end;
+}
+
+u64 VMManager::GetHeapRegionSize() const {
+ return heap_region_end - heap_region_base;
+}
+
+VAddr VMManager::GetMapRegionBaseAddress() const {
+ return map_region_base;
+}
+
+VAddr VMManager::GetMapRegionEndAddress() const {
+ return map_region_end;
+}
+
+u64 VMManager::GetMapRegionSize() const {
+ return map_region_end - map_region_base;
+}
+
+VAddr VMManager::GetNewMapRegionBaseAddress() const {
+ return new_map_region_base;
+}
+
+VAddr VMManager::GetNewMapRegionEndAddress() const {
+ return new_map_region_end;
+}
+
+u64 VMManager::GetNewMapRegionSize() const {
+ return new_map_region_end - new_map_region_base;
+}
+
+VAddr VMManager::GetTLSIORegionBaseAddress() const {
+ return tls_io_region_base;
+}
+
+VAddr VMManager::GetTLSIORegionEndAddress() const {
+ return tls_io_region_end;
+}
+
+u64 VMManager::GetTLSIORegionSize() const {
+ return tls_io_region_end - tls_io_region_base;
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index de75036c0..0ce240126 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -12,6 +12,10 @@
#include "core/memory.h"
#include "core/memory_hook.h"
+namespace FileSys {
+enum class ProgramAddressSpaceType : u8;
+}
+
namespace Kernel {
enum class VMAType : u8 {
@@ -130,7 +134,7 @@ public:
~VMManager();
/// Clears the address space map, re-initializing with a single free area.
- void Reset();
+ void Reset(FileSys::ProgramAddressSpaceType type);
/// Finds the VMA in which the given address is included in, or `vma_map.end()`.
VMAHandle FindVMA(VAddr target) const;
@@ -195,12 +199,57 @@ public:
/// Gets the total heap usage, used by svcGetInfo
u64 GetTotalHeapUsage() const;
- /// Gets the total address space base address, used by svcGetInfo
+ /// Gets the address space base address, used by svcGetInfo
VAddr GetAddressSpaceBaseAddr() const;
/// Gets the total address space address size, used by svcGetInfo
u64 GetAddressSpaceSize() const;
+ /// Gets the base address of the code region.
+ VAddr GetCodeRegionBaseAddress() const;
+
+ /// Gets the end address of the code region.
+ VAddr GetCodeRegionEndAddress() const;
+
+ /// Gets the total size of the code region in bytes.
+ u64 GetCodeRegionSize() const;
+
+ /// Gets the base address of the heap region.
+ VAddr GetHeapRegionBaseAddress() const;
+
+ /// Gets the end address of the heap region;
+ VAddr GetHeapRegionEndAddress() const;
+
+ /// Gets the total size of the heap region in bytes.
+ u64 GetHeapRegionSize() const;
+
+ /// Gets the base address of the map region.
+ VAddr GetMapRegionBaseAddress() const;
+
+ /// Gets the end address of the map region.
+ VAddr GetMapRegionEndAddress() const;
+
+ /// Gets the total size of the map region in bytes.
+ u64 GetMapRegionSize() const;
+
+ /// Gets the base address of the new map region.
+ VAddr GetNewMapRegionBaseAddress() const;
+
+ /// Gets the end address of the new map region.
+ VAddr GetNewMapRegionEndAddress() const;
+
+ /// Gets the total size of the new map region in bytes.
+ u64 GetNewMapRegionSize() const;
+
+ /// Gets the base address of the TLS IO region.
+ VAddr GetTLSIORegionBaseAddress() const;
+
+ /// Gets the end address of the TLS IO region.
+ VAddr GetTLSIORegionEndAddress() const;
+
+ /// Gets the total size of the TLS IO region in bytes.
+ u64 GetTLSIORegionSize() const;
+
/// Each VMManager has its own page table, which is set as the main one when the owning process
/// is scheduled.
Memory::PageTable page_table;
@@ -240,5 +289,36 @@ private:
/// Updates the pages corresponding to this VMA so they match the VMA's attributes.
void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
+
+ /// Initializes memory region ranges to adhere to a given address space type.
+ void InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type);
+
+ /// Clears the underlying map and page table.
+ void Clear();
+
+ /// Clears out the VMA map, unmapping any previously mapped ranges.
+ void ClearVMAMap();
+
+ /// Clears out the page table
+ void ClearPageTable();
+
+ u32 address_space_width = 0;
+ VAddr address_space_base = 0;
+ VAddr address_space_end = 0;
+
+ VAddr code_region_base = 0;
+ VAddr code_region_end = 0;
+
+ VAddr heap_region_base = 0;
+ VAddr heap_region_end = 0;
+
+ VAddr map_region_base = 0;
+ VAddr map_region_end = 0;
+
+ VAddr new_map_region_base = 0;
+ VAddr new_map_region_end = 0;
+
+ VAddr tls_io_region_base = 0;
+ VAddr tls_io_region_end = 0;
};
} // namespace Kernel
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 2b8f78136..44d62ab7f 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -14,7 +14,6 @@
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/deconstructed_rom_directory.h"
#include "core/loader/nso.h"
@@ -127,10 +126,13 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
metadata.Print();
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
- if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) {
+ if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
+ arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
return ResultStatus::Error32BitISA;
}
+ process->LoadFromMetadata(metadata);
+
// Load NSO modules
VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
@@ -145,11 +147,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
}
}
- auto& kernel = Core::System::GetInstance().Kernel();
- process->program_id = metadata.GetTitleID();
- process->svc_access_mask.set();
- process->resource_limit =
- kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),
metadata.GetMainThreadStackSize());
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 0e2af20b4..00d8a82b8 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -12,7 +12,6 @@
#include "core/core.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
#include "core/loader/elf.h"
#include "core/memory.h"
@@ -400,13 +399,6 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
codeset->name = file->GetName();
process->LoadModule(codeset, codeset->entrypoint);
- process->svc_access_mask.set();
-
- // Attach the default resource limit (APPLICATION) to the process
- auto& kernel = Core::System::GetInstance().Kernel();
- process->resource_limit =
- kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
-
process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index c49ec34ab..2385012eb 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -16,7 +16,6 @@
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
#include "core/loader/nro.h"
#include "core/memory.h"
@@ -187,10 +186,6 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
return ResultStatus::ErrorLoadingNRO;
}
- auto& kernel = Core::System::GetInstance().Kernel();
- process->svc_access_mask.set();
- process->resource_limit =
- kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(base_addr, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 78a4438c4..9fd9933fb 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -13,7 +13,6 @@
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
#include "core/loader/nso.h"
#include "core/memory.h"
@@ -162,10 +161,6 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
LoadModule(file, Memory::PROCESS_IMAGE_VADDR);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), Memory::PROCESS_IMAGE_VADDR);
- auto& kernel = Core::System::GetInstance().Kernel();
- process->svc_access_mask.set();
- process->resource_limit =
- kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(Memory::PROCESS_IMAGE_VADDR, Kernel::THREADPRIO_DEFAULT,
Memory::DEFAULT_STACK_SIZE);