summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuri Kunde Schlesner <yuriks@yuriks.net>2015-08-06 02:39:53 +0200
committerYuri Kunde Schlesner <yuriks@yuriks.net>2015-08-16 06:03:48 +0200
commit14eca982f4da2bfd4d2c105bc33722e88e59da5f (patch)
treed812de676c6e2d056ac43abec89251aa36162165
parentKernel: Add more infrastructure to support different memory layouts (diff)
downloadyuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar
yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.gz
yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.bz2
yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.lz
yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.xz
yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.zst
yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.zip
-rw-r--r--src/core/hle/function_wrappers.h8
-rw-r--r--src/core/hle/kernel/process.cpp10
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/thread.cpp4
-rw-r--r--src/core/hle/svc.cpp48
-rw-r--r--src/core/memory.h4
6 files changed, 73 insertions, 3 deletions
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 1a0518926..5846a161b 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -172,6 +172,14 @@ template<ResultCode func(u32, s64, s64)> void Wrap() {
FuncReturn(func(PARAM(0), param1, param2).raw);
}
+template<ResultCode func(s64*, Handle, u32)> void Wrap() {
+ s64 param_1 = 0;
+ u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
+ Core::g_app_core->SetReg(1, (u32)param_1);
+ Core::g_app_core->SetReg(2, (u32)(param_1 >> 32));
+ FuncReturn(retval);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u32
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 1f45e6cf8..124047a53 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -110,6 +110,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
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;
};
// Map CodeSet segments
@@ -121,6 +122,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked
).Unwrap();
+ misc_memory_used += stack_size;
vm_manager.LogLayout(Log::Level::Debug);
Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority);
@@ -162,6 +164,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private));
vm_manager.Reprotect(vma, perms);
+ heap_used += size;
+
return MakeResult<VAddr>(heap_end - size);
}
@@ -173,6 +177,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
ResultCode result = vm_manager.UnmapRange(target, size);
if (result.IsError()) return result;
+ heap_used -= size;
+
return RESULT_SUCCESS;
}
@@ -206,6 +212,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous));
vm_manager.Reprotect(vma, perms);
+ linear_heap_used += size;
+
return MakeResult<VAddr>(target);
}
@@ -226,6 +234,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
ResultCode result = vm_manager.UnmapRange(target, size);
if (result.IsError()) return result;
+ linear_heap_used -= size;
+
if (target + size == heap_end) {
// End of linear heap has been freed, so check what's the last allocated block in it and
// reduce the size.
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 7c3a78b9e..60e17f251 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -136,6 +136,8 @@ public:
// The left/right bounds of the address space covered by heap_memory.
VAddr heap_start = 0, heap_end = 0;
+ u32 heap_used = 0, linear_heap_used = 0, misc_memory_used = 0;
+
MemoryRegionInfo* memory_region = nullptr;
/// Bitmask of the used TLS slots
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 29ea6d531..c10126513 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -117,6 +117,7 @@ void Thread::Stop() {
wait_objects.clear();
Kernel::g_current_process->used_tls_slots[tls_index] = false;
+ g_current_process->misc_memory_used -= Memory::TLS_ENTRY_SIZE;
HLE::Reschedule(__func__);
}
@@ -414,6 +415,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
}
ASSERT_MSG(thread->tls_index != -1, "Out of TLS space");
+ g_current_process->misc_memory_used += Memory::TLS_ENTRY_SIZE;
// TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
// to initialize the context
@@ -504,7 +506,7 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
}
VAddr Thread::GetTLSAddress() const {
- return Memory::TLS_AREA_VADDR + tls_index * 0x200;
+ return Memory::TLS_AREA_VADDR + tls_index * Memory::TLS_ENTRY_SIZE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index e1a416def..89ac45a6f 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -774,6 +774,52 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
return RESULT_SUCCESS;
}
+static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
+ LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, type);
+
+ using Kernel::Process;
+ Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
+ if (process == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ switch (type) {
+ case 0:
+ case 2:
+ // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
+ // what's the difference between them.
+ *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
+ break;
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ // These are valid, but not implemented yet
+ LOG_ERROR(Kernel_SVC, "unimplemented GetProcessInfo type=%u", type);
+ break;
+ case 20:
+ *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase();
+ break;
+ default:
+ LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type);
+
+ if (type >= 21 && type <= 23) {
+ return ResultCode( // 0xE0E01BF4
+ ErrorDescription::NotImplemented, ErrorModule::OS,
+ ErrorSummary::InvalidArgument, ErrorLevel::Usage);
+ } else {
+ return ResultCode( // 0xD8E007ED
+ ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
+ ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
+ }
+ break;
+ }
+
+ return RESULT_SUCCESS;
+}
+
namespace {
struct FunctionDef {
using Func = void();
@@ -828,7 +874,7 @@ static const FunctionDef SVC_Table[] = {
{0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"},
{0x29, nullptr, "GetHandleInfo"},
{0x2A, nullptr, "GetSystemInfo"},
- {0x2B, nullptr, "GetProcessInfo"},
+ {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"},
{0x2C, nullptr, "GetThreadInfo"},
{0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"},
{0x2E, nullptr, "SendSyncRequest1"},
diff --git a/src/core/memory.h b/src/core/memory.h
index d1d32f0dd..c136cbd55 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -105,9 +105,11 @@ enum : VAddr {
// hardcoded value.
/// Area where TLS (Thread-Local Storage) buffers are allocated.
TLS_AREA_VADDR = 0x1FF82000,
- TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads
+ TLS_ENTRY_SIZE = 0x200,
+ TLS_AREA_SIZE = 300 * TLS_ENTRY_SIZE, // Allows for up to 300 threads
TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
+
/// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.
NEW_LINEAR_HEAP_VADDR = 0x30000000,
NEW_LINEAR_HEAP_SIZE = 0x10000000,