summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/mutex.cpp3
-rw-r--r--src/core/hle/kernel/mutex.h3
-rw-r--r--src/core/hle/kernel/process.cpp47
-rw-r--r--src/core/hle/kernel/process.h17
-rw-r--r--src/core/hle/kernel/semaphore.cpp3
-rw-r--r--src/core/hle/kernel/semaphore.h3
-rw-r--r--src/core/hle/kernel/thread.cpp9
-rw-r--r--src/core/hle/kernel/thread.h8
-rw-r--r--src/core/hle/kernel/vm_manager.cpp28
-rw-r--r--src/core/hle/kernel/vm_manager.h20
10 files changed, 82 insertions, 59 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 2cbca5e5b..30dade552 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -25,10 +25,11 @@ void ReleaseThreadMutexes(Thread* thread) {
Mutex::Mutex() {}
Mutex::~Mutex() {}
-SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
+SharedPtr<Mutex> Mutex::Create(bool initial_locked, VAddr addr, std::string name) {
SharedPtr<Mutex> mutex(new Mutex);
mutex->lock_count = 0;
+ mutex->addr = addr;
mutex->name = std::move(name);
mutex->holding_thread = nullptr;
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index bacacd690..503d3ee75 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -21,7 +21,7 @@ public:
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
- static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
+ static SharedPtr<Mutex> Create(bool initial_locked, VAddr addr, std::string name = "Unknown");
std::string GetTypeName() const override {
return "Mutex";
@@ -39,6 +39,7 @@ public:
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
+ VAddr addr;
/**
* Elevate the mutex priority to the best priority
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index cf3163e0f..9e145866f 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -30,10 +30,10 @@ CodeSet::~CodeSet() {}
u32 Process::next_process_id;
-SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) {
+SharedPtr<Process> Process::Create(std::string&& name) {
SharedPtr<Process> process(new Process);
- process->codeset = std::move(code_set);
+ process->name = std::move(name);
process->flags.raw = 0;
process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
@@ -112,25 +112,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
}
}
-void Process::Run(s32 main_thread_priority, u32 stack_size) {
- memory_region = GetMemoryRegion(flags.memory_region);
-
- auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
- MemoryState memory_state) {
- auto vma = vm_manager
- .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size,
- memory_state)
- .Unwrap();
- vm_manager.Reprotect(vma, permissions);
- misc_memory_used += segment.size;
- memory_region->used += segment.size;
- };
-
- // Map CodeSet segments
- MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code);
- MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code);
- MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private);
-
+void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
// Allocate and map stack
vm_manager
.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
@@ -147,7 +129,28 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
}
vm_manager.LogLayout(Log::Level::Debug);
- Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this);
+
+ Kernel::SetupMainThread(entry_point, main_thread_priority, this);
+}
+
+void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
+ memory_region = GetMemoryRegion(flags.memory_region);
+
+ auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
+ MemoryState memory_state) {
+ auto vma = vm_manager
+ .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, segment.size,
+ memory_state)
+ .Unwrap();
+ vm_manager.Reprotect(vma, permissions);
+ misc_memory_used += segment.size;
+ memory_region->used += segment.size;
+ };
+
+ // Map CodeSet segments
+ MapSegment(module_->code, VMAPermission::ReadWrite, MemoryState::Private);
+ MapSegment(module_->rodata, VMAPermission::Read, MemoryState::Static);
+ MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::Static);
}
VAddr Process::GetLinearHeapAreaAddress() const {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index b52211d2a..f05f2703e 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -79,7 +79,11 @@ struct CodeSet final : public Object {
u32 size = 0;
};
- Segment code, rodata, data;
+ Segment segments[3];
+ Segment& code = segments[0];
+ Segment& rodata = segments[1];
+ Segment& data = segments[2];
+
VAddr entrypoint;
private:
@@ -89,13 +93,13 @@ private:
class Process final : public Object {
public:
- static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);
+ static SharedPtr<Process> Create(std::string&& name);
std::string GetTypeName() const override {
return "Process";
}
std::string GetName() const override {
- return codeset->name;
+ return name;
}
static const HandleType HANDLE_TYPE = HandleType::Process;
@@ -105,7 +109,6 @@ public:
static u32 next_process_id;
- SharedPtr<CodeSet> codeset;
/// Resource limit descriptor for this process
SharedPtr<ResourceLimit> resource_limit;
@@ -134,7 +137,9 @@ public:
/**
* Applies address space changes and launches the process main thread.
*/
- void Run(s32 main_thread_priority, u32 stack_size);
+ void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size);
+
+ void LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr);
///////////////////////////////////////////////////////////////////////////////////////////////
// Memory Management
@@ -160,6 +165,8 @@ public:
/// This vector will grow as more pages are allocated for new threads.
std::vector<std::bitset<8>> tls_slots;
+ std::string name;
+
VAddr GetLinearHeapAreaAddress() const;
VAddr GetLinearHeapBase() const;
VAddr GetLinearHeapLimit() const;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index fcf586728..2605b2595 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -13,7 +13,7 @@ namespace Kernel {
Semaphore::Semaphore() {}
Semaphore::~Semaphore() {}
-ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
+ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, VAddr address,
std::string name) {
if (initial_count > max_count)
@@ -25,6 +25,7 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou
// and the rest is reserved for the caller thread
semaphore->max_count = max_count;
semaphore->available_count = initial_count;
+ semaphore->address = address;
semaphore->name = std::move(name);
return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 7b0cacf2e..77c491a24 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -22,7 +22,7 @@ public:
* @param name Optional name of semaphore
* @return The created semaphore
*/
- static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
+ static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, VAddr address,
std::string name = "Unknown");
std::string GetTypeName() const override {
@@ -39,6 +39,7 @@ public:
s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
s32 available_count; ///< Number of free slots left in the semaphore
+ VAddr address;
std::string name; ///< Name of semaphore (optional)
bool ShouldWait(Thread* thread) const override;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 0f7970ebe..75df49ac2 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -358,8 +358,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
* @param entry_point Address of entry point for execution
* @param arg User argument for thread
*/
-static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_top,
- u32 entry_point, u32 arg) {
+static void ResetThreadContext(ARM_Interface::ThreadContext& context, VAddr stack_top,
+ VAddr entry_point, u64 arg) {
memset(&context, 0, sizeof(ARM_Interface::ThreadContext));
context.cpu_registers[0] = arg;
@@ -446,7 +446,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
// Map the page to the current process' address space.
// TODO(Subv): Find the correct MemoryState for this region.
vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
- linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::Private);
+ linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::Static);
}
// Mark the slot as used
@@ -495,6 +495,9 @@ void Thread::BoostPriority(u32 priority) {
}
SharedPtr<Thread> SetupMainThread(u32 entry_point, u32 priority, SharedPtr<Process> owner_process) {
+ // Setup page table so we can write to memory
+ SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
+
// Initialize new "main" thread
auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
Memory::HEAP_VADDR_END, owner_process);
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 314fba81f..fafcab156 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -184,8 +184,8 @@ public:
u32 thread_id;
u32 status;
- u32 entry_point;
- u32 stack_top;
+ VAddr entry_point;
+ VAddr stack_top;
u32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
u32 current_priority; ///< Current thread priority, can be temporarily changed
@@ -250,13 +250,13 @@ void Reschedule();
* Arbitrate the highest priority thread that is waiting
* @param address The address for which waiting threads should be arbitrated
*/
-Thread* ArbitrateHighestPriorityThread(u32 address);
+Thread* ArbitrateHighestPriorityThread(VAddr address);
/**
* Arbitrate all threads currently waiting.
* @param address The address for which waiting threads should be arbitrated
*/
-void ArbitrateAllThreads(u32 address);
+void ArbitrateAllThreads(VAddr address);
/**
* Gets the current thread
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 7a007c065..9762ef535 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -4,8 +4,10 @@
#include <iterator>
#include "common/assert.h"
+#include "core/arm/arm_interface.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/vm_manager.h"
+#include "core/core.h"
#include "core/memory.h"
#include "core/memory_setup.h"
#include "core/mmio.h"
@@ -60,7 +62,7 @@ void VMManager::Reset() {
page_table.attributes.fill(Memory::PageType::Unmapped);
page_table.cached_res_count.fill(0);
- UpdatePageTableForVMA(initial_vma);
+ //UpdatePageTableForVMA(initial_vma);
}
VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
@@ -73,7 +75,7 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
std::shared_ptr<std::vector<u8>> block,
- size_t offset, u32 size,
+ size_t offset, u64 size,
MemoryState state) {
ASSERT(block != nullptr);
ASSERT(offset + size <= block->size());
@@ -83,6 +85,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
+ Core::CPU().MapBackingMemory(target, size, block->data() + offset, VMAPermission::ReadWriteExecute);
+
final_vma.type = VMAType::AllocatedMemoryBlock;
final_vma.permissions = VMAPermission::ReadWrite;
final_vma.meminfo_state = state;
@@ -93,7 +97,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
}
-ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size,
+ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u64 size,
MemoryState state) {
ASSERT(memory != nullptr);
@@ -102,6 +106,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
+ Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
+
final_vma.type = VMAType::BackingMemory;
final_vma.permissions = VMAPermission::ReadWrite;
final_vma.meminfo_state = state;
@@ -111,7 +117,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
}
-ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
+ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u64 size,
MemoryState state,
Memory::MMIORegionPointer mmio_handler) {
// This is the appropriately sized VMA that will turn into our allocation.
@@ -145,7 +151,7 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
return MergeAdjacent(vma_handle);
}
-ResultCode VMManager::UnmapRange(VAddr target, u32 size) {
+ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size));
VAddr target_end = target + size;
@@ -170,7 +176,7 @@ VMManager::VMAHandle VMManager::Reprotect(VMAHandle vma_handle, VMAPermission ne
return MergeAdjacent(iter);
}
-ResultCode VMManager::ReprotectRange(VAddr target, u32 size, VMAPermission new_perms) {
+ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_perms) {
CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size));
VAddr target_end = target + size;
@@ -213,7 +219,7 @@ VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
return vma_map.erase(iter, iter); // Erases an empty range of elements
}
-ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) {
+ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) {
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%8X", size);
ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%08X", base);
@@ -229,8 +235,8 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) {
return ERR_INVALID_ADDRESS_STATE;
}
- u32 start_in_vma = base - vma.base;
- u32 end_in_vma = start_in_vma + size;
+ u64 start_in_vma = base - vma.base;
+ u64 end_in_vma = start_in_vma + size;
if (end_in_vma > vma.size) {
// Requested allocation doesn't fit inside VMA
@@ -249,7 +255,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) {
return MakeResult<VMAIter>(vma_handle);
}
-ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u32 size) {
+ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) {
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%8X", size);
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%08X", target);
@@ -278,7 +284,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u32 size) {
return MakeResult<VMAIter>(begin_vma);
}
-VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) {
+VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u64 offset_in_vma) {
VirtualMemoryArea& old_vma = vma_handle->second;
VirtualMemoryArea new_vma = old_vma; // Make a copy of the VMA
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 1302527bb..cb5bb8243 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -64,7 +64,7 @@ struct VirtualMemoryArea {
/// Virtual base address of the region.
VAddr base = 0;
/// Size of the region.
- u32 size = 0;
+ u64 size = 0;
VMAType type = VMAType::Free;
VMAPermission permissions = VMAPermission::None;
@@ -109,7 +109,7 @@ public:
* used.
* @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000.
*/
- static const u32 MAX_ADDRESS = 0x40000000;
+ static const VAddr MAX_ADDRESS = 0x8000000000;
/**
* A map covering the entirety of the managed address space, keyed by the `base` field of each
@@ -142,7 +142,7 @@ public:
* @param state MemoryState tag to attach to the VMA.
*/
ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
- size_t offset, u32 size, MemoryState state);
+ size_t offset, u64 size, MemoryState state);
/**
* Maps an unmanaged host memory pointer at a given address.
@@ -152,7 +152,7 @@ public:
* @param size Size of the mapping.
* @param state MemoryState tag to attach to the VMA.
*/
- ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u32 size, MemoryState state);
+ ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state);
/**
* Maps a memory-mapped IO region at a given address.
@@ -163,17 +163,17 @@ public:
* @param state MemoryState tag to attach to the VMA.
* @param mmio_handler The handler that will implement read and write for this MMIO region.
*/
- ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
+ ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u64 size, MemoryState state,
Memory::MMIORegionPointer mmio_handler);
/// Unmaps a range of addresses, splitting VMAs as necessary.
- ResultCode UnmapRange(VAddr target, u32 size);
+ ResultCode UnmapRange(VAddr target, u64 size);
/// Changes the permissions of the given VMA.
VMAHandle Reprotect(VMAHandle vma, VMAPermission new_perms);
/// Changes the permissions of a range of addresses, splitting VMAs as necessary.
- ResultCode ReprotectRange(VAddr target, u32 size, VMAPermission new_perms);
+ ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms);
/**
* Scans all VMAs and updates the page table range of any that use the given vector as backing
@@ -201,19 +201,19 @@ private:
* Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing
* the appropriate error checking.
*/
- ResultVal<VMAIter> CarveVMA(VAddr base, u32 size);
+ ResultVal<VMAIter> CarveVMA(VAddr base, u64 size);
/**
* Splits the edges of the given range of non-Free VMAs so that there is a VMA split at each
* end of the range.
*/
- ResultVal<VMAIter> CarveVMARange(VAddr base, u32 size);
+ ResultVal<VMAIter> CarveVMARange(VAddr base, u64 size);
/**
* Splits a VMA in two, at the specified offset.
* @returns the right side of the split, with the original iterator becoming the left side.
*/
- VMAIter SplitVMA(VMAIter vma, u32 offset_in_vma);
+ VMAIter SplitVMA(VMAIter vma, u64 offset_in_vma);
/**
* Checks for and merges the specified VMA with adjacent ones if possible.