aboutsummaryrefslogtreecommitdiff
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/handle_table.cpp11
-rw-r--r--src/core/hle/kernel/handle_table.h15
-rw-r--r--src/core/hle/kernel/kernel.cpp79
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/process.cpp7
-rw-r--r--src/core/hle/kernel/process.h4
-rw-r--r--src/core/hle/kernel/resource_limit.cpp75
-rw-r--r--src/core/hle/kernel/resource_limit.h98
-rw-r--r--src/core/hle/kernel/shared_memory.cpp22
-rw-r--r--src/core/hle/kernel/shared_memory.h48
-rw-r--r--src/core/hle/kernel/svc.cpp56
-rw-r--r--src/core/hle/kernel/vm_manager.cpp6
-rw-r--r--src/core/hle/kernel/vm_manager.h3
13 files changed, 186 insertions, 244 deletions
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 5ee5c05e3..1bf79b692 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -12,12 +12,23 @@
#include "core/hle/kernel/thread.h"
namespace Kernel {
+namespace {
+constexpr u16 GetSlot(Handle handle) {
+ return handle >> 15;
+}
+
+constexpr u16 GetGeneration(Handle handle) {
+ return handle & 0x7FFF;
+}
+} // Anonymous namespace
HandleTable::HandleTable() {
next_generation = 1;
Clear();
}
+HandleTable::~HandleTable() = default;
+
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
DEBUG_ASSERT(obj != nullptr);
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index 9e2f33e8a..e3f3e3fb8 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -43,6 +43,7 @@ enum KernelHandle : Handle {
class HandleTable final : NonCopyable {
public:
HandleTable();
+ ~HandleTable();
/**
* Allocates a handle for the given object.
@@ -89,18 +90,8 @@ public:
void Clear();
private:
- /**
- * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
- * reduced by ExHeader values, but this is not emulated here.
- */
- static const std::size_t MAX_COUNT = 4096;
-
- static u16 GetSlot(Handle handle) {
- return handle >> 15;
- }
- static u16 GetGeneration(Handle handle) {
- return handle & 0x7FFF;
- }
+ /// This is the maximum limit of handles allowed per process in Horizon
+ static constexpr std::size_t MAX_COUNT = 1024;
/// Stores the Object referenced by the handle or null if the slot is empty.
std::array<SharedPtr<Object>, MAX_COUNT> objects;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1fd4ba5d2..e441c5bc6 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -105,7 +105,7 @@ struct KernelCore::Impl {
void Initialize(KernelCore& kernel) {
Shutdown();
- InitializeResourceLimits(kernel);
+ InitializeSystemResourceLimit(kernel);
InitializeThreads();
InitializeTimers();
}
@@ -118,7 +118,7 @@ struct KernelCore::Impl {
process_list.clear();
current_process = nullptr;
- resource_limits.fill(nullptr);
+ system_resource_limit = nullptr;
thread_wakeup_callback_handle_table.Clear();
thread_wakeup_event_type = nullptr;
@@ -129,63 +129,17 @@ struct KernelCore::Impl {
named_ports.clear();
}
- void InitializeResourceLimits(KernelCore& kernel) {
- // Create the four resource limits that the system uses
- // Create the APPLICATION resource limit
- SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
- resource_limit->max_priority = 0x18;
- resource_limit->max_commit = 0x4000000;
- resource_limit->max_threads = 0x20;
- resource_limit->max_events = 0x20;
- resource_limit->max_mutexes = 0x20;
- resource_limit->max_semaphores = 0x8;
- resource_limit->max_timers = 0x8;
- resource_limit->max_shared_mems = 0x10;
- resource_limit->max_address_arbiters = 0x2;
- resource_limit->max_cpu_time = 0x1E;
- resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
-
- // Create the SYS_APPLET resource limit
- resource_limit = ResourceLimit::Create(kernel, "System Applets");
- resource_limit->max_priority = 0x4;
- resource_limit->max_commit = 0x5E00000;
- resource_limit->max_threads = 0x1D;
- resource_limit->max_events = 0xB;
- resource_limit->max_mutexes = 0x8;
- resource_limit->max_semaphores = 0x4;
- resource_limit->max_timers = 0x4;
- resource_limit->max_shared_mems = 0x8;
- resource_limit->max_address_arbiters = 0x3;
- resource_limit->max_cpu_time = 0x2710;
- resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
-
- // Create the LIB_APPLET resource limit
- resource_limit = ResourceLimit::Create(kernel, "Library Applets");
- resource_limit->max_priority = 0x4;
- resource_limit->max_commit = 0x600000;
- resource_limit->max_threads = 0xE;
- resource_limit->max_events = 0x8;
- resource_limit->max_mutexes = 0x8;
- resource_limit->max_semaphores = 0x4;
- resource_limit->max_timers = 0x4;
- resource_limit->max_shared_mems = 0x8;
- resource_limit->max_address_arbiters = 0x1;
- resource_limit->max_cpu_time = 0x2710;
- resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
-
- // Create the OTHER resource limit
- resource_limit = ResourceLimit::Create(kernel, "Others");
- resource_limit->max_priority = 0x4;
- resource_limit->max_commit = 0x2180000;
- resource_limit->max_threads = 0xE1;
- resource_limit->max_events = 0x108;
- resource_limit->max_mutexes = 0x25;
- resource_limit->max_semaphores = 0x43;
- resource_limit->max_timers = 0x2C;
- resource_limit->max_shared_mems = 0x1F;
- resource_limit->max_address_arbiters = 0x2D;
- resource_limit->max_cpu_time = 0x3E8;
- resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
+ // Creates the default system resource limit
+ void InitializeSystemResourceLimit(KernelCore& kernel) {
+ system_resource_limit = ResourceLimit::Create(kernel, "System");
+
+ // If setting the default system values fails, then something seriously wrong has occurred.
+ ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x200000000)
+ .IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
}
void InitializeThreads() {
@@ -208,7 +162,7 @@ struct KernelCore::Impl {
std::vector<SharedPtr<Process>> process_list;
Process* current_process = nullptr;
- std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
+ SharedPtr<ResourceLimit> system_resource_limit;
/// The event type of the generic timer callback event
CoreTiming::EventType* timer_callback_event_type = nullptr;
@@ -239,9 +193,8 @@ void KernelCore::Shutdown() {
impl->Shutdown();
}
-SharedPtr<ResourceLimit> KernelCore::ResourceLimitForCategory(
- ResourceLimitCategory category) const {
- return impl->resource_limits.at(static_cast<std::size_t>(category));
+SharedPtr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
+ return impl->system_resource_limit;
}
SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7f822d524..ea00c89f5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -24,8 +24,6 @@ class ResourceLimit;
class Thread;
class Timer;
-enum class ResourceLimitCategory : u8;
-
/// Represents a single instance of the kernel.
class KernelCore {
private:
@@ -47,8 +45,8 @@ public:
/// Clears all resources in use by the kernel instance.
void Shutdown();
- /// Retrieves a shared pointer to a ResourceLimit identified by the given category.
- SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const;
+ /// Retrieves a shared pointer to the system resource limit instance.
+ SharedPtr<ResourceLimit> GetSystemResourceLimit() const;
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index f06b6bb55..7ca538401 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <memory>
+#include <random>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
@@ -28,7 +29,7 @@ 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->resource_limit = kernel.GetSystemResourceLimit();
process->status = ProcessStatus::Created;
process->program_id = 0;
process->process_id = kernel.CreateNewProcessID();
@@ -252,8 +253,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
return vm_manager.HeapFree(target, size);
}
-ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
- return vm_manager.MirrorMemory(dst_addr, src_addr, size);
+ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) {
+ return vm_manager.MirrorMemory(dst_addr, src_addr, size, state);
}
ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index cf48787ce..ada845c7f 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -8,7 +8,6 @@
#include <bitset>
#include <cstddef>
#include <memory>
-#include <random>
#include <string>
#include <vector>
#include <boost/container/static_vector.hpp>
@@ -259,7 +258,8 @@ public:
ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
ResultCode HeapFree(VAddr target, u32 size);
- ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size);
+ ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size,
+ MemoryState state = MemoryState::Mapped);
ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index b253a680f..2f9695005 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -2,12 +2,16 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cstring>
-#include "common/assert.h"
-#include "common/logging/log.h"
+#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/resource_limit.h"
+#include "core/hle/result.h"
namespace Kernel {
+namespace {
+constexpr std::size_t ResourceTypeToIndex(ResourceType type) {
+ return static_cast<std::size_t>(type);
+}
+} // Anonymous namespace
ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
ResourceLimit::~ResourceLimit() = default;
@@ -19,59 +23,22 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel, std::string n
return resource_limit;
}
-s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
- switch (resource) {
- case ResourceType::Commit:
- return current_commit;
- case ResourceType::Thread:
- return current_threads;
- case ResourceType::Event:
- return current_events;
- case ResourceType::Mutex:
- return current_mutexes;
- case ResourceType::Semaphore:
- return current_semaphores;
- case ResourceType::Timer:
- return current_timers;
- case ResourceType::SharedMemory:
- return current_shared_mems;
- case ResourceType::AddressArbiter:
- return current_address_arbiters;
- case ResourceType::CPUTime:
- return current_cpu_time;
- default:
- LOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
- UNIMPLEMENTED();
- return 0;
- }
+s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
+ return values.at(ResourceTypeToIndex(resource));
+}
+
+s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
+ return limits.at(ResourceTypeToIndex(resource));
}
-u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
- switch (resource) {
- case ResourceType::Priority:
- return max_priority;
- case ResourceType::Commit:
- return max_commit;
- case ResourceType::Thread:
- return max_threads;
- case ResourceType::Event:
- return max_events;
- case ResourceType::Mutex:
- return max_mutexes;
- case ResourceType::Semaphore:
- return max_semaphores;
- case ResourceType::Timer:
- return max_timers;
- case ResourceType::SharedMemory:
- return max_shared_mems;
- case ResourceType::AddressArbiter:
- return max_address_arbiters;
- case ResourceType::CPUTime:
- return max_cpu_time;
- default:
- LOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
- UNIMPLEMENTED();
- return 0;
+ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) {
+ const auto index = ResourceTypeToIndex(resource);
+
+ if (value < values[index]) {
+ return ERR_INVALID_STATE;
}
+
+ values[index] = value;
+ return RESULT_SUCCESS;
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 219e49562..bec065543 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -4,31 +4,25 @@
#pragma once
+#include <array>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
+union ResultCode;
+
namespace Kernel {
class KernelCore;
-enum class ResourceLimitCategory : u8 {
- APPLICATION = 0,
- SYS_APPLET = 1,
- LIB_APPLET = 2,
- OTHER = 3
-};
-
enum class ResourceType {
- Priority = 0,
- Commit = 1,
- Thread = 2,
- Event = 3,
- Mutex = 4,
- Semaphore = 5,
- Timer = 6,
- SharedMemory = 7,
- AddressArbiter = 8,
- CPUTime = 9,
+ PhysicalMemory,
+ Threads,
+ Events,
+ TransferMemory,
+ Sessions,
+
+ // Used as a count, not an actual type.
+ ResourceTypeCount
};
class ResourceLimit final : public Object {
@@ -55,61 +49,51 @@ public:
* @param resource Requested resource type
* @returns The current value of the resource type
*/
- s32 GetCurrentResourceValue(ResourceType resource) const;
+ s64 GetCurrentResourceValue(ResourceType resource) const;
/**
* Gets the max value for the specified resource.
* @param resource Requested resource type
* @returns The max value of the resource type
*/
- u32 GetMaxResourceValue(ResourceType resource) const;
-
- /// Name of resource limit object.
- std::string name;
-
- /// Max thread priority that a process in this category can create
- s32 max_priority = 0;
-
- /// Max memory that processes in this category can use
- s32 max_commit = 0;
+ s64 GetMaxResourceValue(ResourceType resource) const;
- ///< Max number of objects that can be collectively created by the processes in this category
- s32 max_threads = 0;
- s32 max_events = 0;
- s32 max_mutexes = 0;
- s32 max_semaphores = 0;
- s32 max_timers = 0;
- s32 max_shared_mems = 0;
- s32 max_address_arbiters = 0;
+ /**
+ * Sets the limit value for a given resource type.
+ *
+ * @param resource The resource type to apply the limit to.
+ * @param value The limit to apply to the given resource type.
+ *
+ * @return A result code indicating if setting the limit value
+ * was successful or not.
+ *
+ * @note The supplied limit value *must* be greater than or equal to
+ * the current resource value for the given resource type,
+ * otherwise ERR_INVALID_STATE will be returned.
+ */
+ ResultCode SetLimitValue(ResourceType resource, s64 value);
- /// Max CPU time that the processes in this category can utilize
- s32 max_cpu_time = 0;
+private:
+ explicit ResourceLimit(KernelCore& kernel);
+ ~ResourceLimit() override;
- // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind
- // that APPLICATION resource limits should not be affected by the objects created by service
- // modules.
+ // TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create
+ // functions
+ //
// Currently we have no way of distinguishing if a Create was called by the running application,
// or by a service module. Approach this once we have separated the service modules into their
// own processes
- /// Current memory that the processes in this category are using
- s32 current_commit = 0;
+ using ResourceArray =
+ std::array<s64, static_cast<std::size_t>(ResourceType::ResourceTypeCount)>;
- ///< Current number of objects among all processes in this category
- s32 current_threads = 0;
- s32 current_events = 0;
- s32 current_mutexes = 0;
- s32 current_semaphores = 0;
- s32 current_timers = 0;
- s32 current_shared_mems = 0;
- s32 current_address_arbiters = 0;
+ /// Maximum values a resource type may reach.
+ ResourceArray limits{};
+ /// Current resource limit values.
+ ResourceArray values{};
- /// Current CPU time that the processes in this category are utilizing
- s32 current_cpu_time = 0;
-
-private:
- explicit ResourceLimit(KernelCore& kernel);
- ~ResourceLimit() override;
+ /// Name of resource limit object.
+ std::string name;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index a016a86b6..0494581f5 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -61,7 +61,7 @@ SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, SharedPtr<Proce
}
SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
- KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size,
+ KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, std::size_t offset, u64 size,
MemoryPermission permissions, MemoryPermission other_permissions, std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));
@@ -78,10 +78,10 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
return shared_memory;
}
-ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
+ResultCode SharedMemory::Map(Process& target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions) {
const MemoryPermission own_other_permissions =
- target_process == owner_process ? this->permissions : this->other_permissions;
+ &target_process == owner_process ? this->permissions : this->other_permissions;
// Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
@@ -106,7 +106,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
VAddr target_address = address;
// Map the memory block into the target process
- auto result = target_process->VMManager().MapMemoryBlock(
+ auto result = target_process.VMManager().MapMemoryBlock(
target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
if (result.Failed()) {
LOG_ERROR(
@@ -116,14 +116,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
return result.Code();
}
- return target_process->VMManager().ReprotectRange(target_address, size,
- ConvertPermissions(permissions));
+ return target_process.VMManager().ReprotectRange(target_address, size,
+ ConvertPermissions(permissions));
}
-ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
+ResultCode SharedMemory::Unmap(Process& target_process, VAddr address) {
// TODO(Subv): Verify what happens if the application tries to unmap an address that is not
// mapped to a SharedMemory.
- return target_process->VMManager().UnmapRange(address, size);
+ return target_process.VMManager().UnmapRange(address, size);
}
VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
@@ -132,7 +132,11 @@ VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
return static_cast<VMAPermission>(masked_permissions);
}
-u8* SharedMemory::GetPointer(u32 offset) {
+u8* SharedMemory::GetPointer(std::size_t offset) {
+ return backing_block->data() + backing_block_offset + offset;
+}
+
+const u8* SharedMemory::GetPointer(std::size_t offset) const {
return backing_block->data() + backing_block_offset + offset;
}
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 2c06bb7ce..0b48db699 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -64,7 +64,7 @@ public:
*/
static SharedPtr<SharedMemory> CreateForApplet(KernelCore& kernel,
std::shared_ptr<std::vector<u8>> heap_block,
- u32 offset, u32 size,
+ std::size_t offset, u64 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
@@ -81,6 +81,11 @@ public:
return HANDLE_TYPE;
}
+ /// Gets the size of the underlying memory block in bytes.
+ u64 GetSize() const {
+ return size;
+ }
+
/**
* Converts the specified MemoryPermission into the equivalent VMAPermission.
* @param permission The MemoryPermission to convert.
@@ -94,44 +99,51 @@ public:
* @param permissions Memory block map permissions (specified by SVC field)
* @param other_permissions Memory block map other permissions (specified by SVC field)
*/
- ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
+ ResultCode Map(Process& target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions);
/**
* Unmaps a shared memory block from the specified address in system memory
- * @param target_process Process from which to umap the memory block.
+ * @param target_process Process from which to unmap the memory block.
* @param address Address in system memory where the shared memory block is mapped
* @return Result code of the unmap operation
*/
- ResultCode Unmap(Process* target_process, VAddr address);
+ ResultCode Unmap(Process& target_process, VAddr address);
/**
* Gets a pointer to the shared memory block
* @param offset Offset from the start of the shared memory block to get pointer
- * @return Pointer to the shared memory block from the specified offset
+ * @return A pointer to the shared memory block from the specified offset
*/
- u8* GetPointer(u32 offset = 0);
+ u8* GetPointer(std::size_t offset = 0);
+
+ /**
+ * Gets a constant pointer to the shared memory block
+ * @param offset Offset from the start of the shared memory block to get pointer
+ * @return A constant pointer to the shared memory block from the specified offset
+ */
+ const u8* GetPointer(std::size_t offset = 0) const;
+
+private:
+ explicit SharedMemory(KernelCore& kernel);
+ ~SharedMemory() override;
- /// Process that created this shared memory block.
- SharedPtr<Process> owner_process;
- /// Address of shared memory block in the owner process if specified.
- VAddr base_address;
/// Backing memory for this shared memory block.
std::shared_ptr<std::vector<u8>> backing_block;
/// Offset into the backing block for this shared memory.
- std::size_t backing_block_offset;
+ std::size_t backing_block_offset = 0;
/// Size of the memory block. Page-aligned.
- u64 size;
+ u64 size = 0;
/// Permission restrictions applied to the process which created the block.
- MemoryPermission permissions;
+ MemoryPermission permissions{};
/// Permission restrictions applied to other processes mapping the block.
- MemoryPermission other_permissions;
+ MemoryPermission other_permissions{};
+ /// Process that created this shared memory block.
+ SharedPtr<Process> owner_process;
+ /// Address of shared memory block in the owner process if specified.
+ VAddr base_address = 0;
/// Name of shared memory object.
std::string name;
-
-private:
- explicit SharedMemory(KernelCore& kernel);
- ~SharedMemory() override;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 2e7c9d094..f287f7c97 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -671,7 +671,8 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
break;
}
default:
- UNIMPLEMENTED();
+ LOG_WARNING(Kernel_SVC, "(STUBBED) Unimplemented svcGetInfo id=0x{:016X}", info_id);
+ return ERR_INVALID_ENUM_VALUE;
}
return RESULT_SUCCESS;
@@ -736,13 +737,6 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
const auto* const current_process = Core::CurrentProcess();
- // Note: The kernel uses the current process's resource limit instead of
- // the one from the thread owner's resource limit.
- const ResourceLimit& resource_limit = current_process->GetResourceLimit();
- if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
- return ERR_INVALID_THREAD_PRIORITY;
- }
-
SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
if (!thread) {
return ERR_INVALID_HANDLE;
@@ -796,7 +790,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_MEMORY_RANGE;
}
- return shared_memory->Map(current_process, addr, permissions_type, MemoryPermission::DontCare);
+ return shared_memory->Map(*current_process, addr, permissions_type, MemoryPermission::DontCare);
}
static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
@@ -826,7 +820,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
return ERR_INVALID_MEMORY_RANGE;
}
- return shared_memory->Unmap(current_process, addr);
+ return shared_memory->Unmap(*current_process, addr);
}
/// Query process memory
@@ -885,10 +879,6 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
}
auto* const current_process = Core::CurrentProcess();
- const ResourceLimit& resource_limit = current_process->GetResourceLimit();
- if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
- return ERR_INVALID_THREAD_PRIORITY;
- }
if (processor_id == THREADPROCESSORID_DEFAULT) {
// Set the target CPU to the one specified in the process' exheader.
@@ -1181,7 +1171,7 @@ static ResultCode CloseHandle(Handle handle) {
/// Reset an event
static ResultCode ResetSignal(Handle handle) {
- LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle);
+ LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
auto event = handle_table.Get<Event>(handle);
@@ -1194,9 +1184,39 @@ static ResultCode ResetSignal(Handle handle) {
/// Creates a TransferMemory object
static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) {
- LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size,
- permissions);
- *handle = 0;
+ LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size,
+ permissions);
+
+ if (!Common::Is4KBAligned(addr)) {
+ LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (!Common::Is4KBAligned(size) || size == 0) {
+ LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (!IsValidAddressRange(addr, size)) {
+ LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})",
+ addr, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ const auto perms = static_cast<MemoryPermission>(permissions);
+ if (perms != MemoryPermission::None && perms != MemoryPermission::Read &&
+ perms != MemoryPermission::ReadWrite) {
+ LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
+ permissions);
+ return ERR_INVALID_MEMORY_PERMISSIONS;
+ }
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto shared_mem_handle = SharedMemory::Create(
+ kernel, handle_table.Get<Process>(CurrentProcess), size, perms, perms, addr);
+
+ CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index ec7fd6150..100f8f6bf 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -298,7 +298,7 @@ ResultCode VMManager::HeapFree(VAddr target, u64 size) {
return RESULT_SUCCESS;
}
-ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
+ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) {
const auto vma = FindVMA(src_addr);
ASSERT_MSG(vma != vma_map.end(), "Invalid memory address");
@@ -312,8 +312,8 @@ ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
const std::shared_ptr<std::vector<u8>>& backing_block = vma->second.backing_block;
const std::size_t backing_block_offset = vma->second.offset + vma_offset;
- CASCADE_RESULT(auto new_vma, MapMemoryBlock(dst_addr, backing_block, backing_block_offset, size,
- MemoryState::Mapped));
+ CASCADE_RESULT(auto new_vma,
+ MapMemoryBlock(dst_addr, backing_block, backing_block_offset, size, state));
// Protect mirror with permissions from old region
Reprotect(new_vma, vma->second.permissions);
// Remove permissions from old region
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 248cc46dc..d522404fe 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -189,7 +189,8 @@ public:
ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
ResultCode HeapFree(VAddr target, u64 size);
- ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size);
+ ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size,
+ MemoryState state = MemoryState::Mapped);
/**
* Scans all VMAs and updates the page table range of any that use the given vector as backing