summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp158
1 files changed, 143 insertions, 15 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index bb64fdfb7..89ac45a6f 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -10,11 +10,11 @@
10#include "common/symbols.h" 10#include "common/symbols.h"
11 11
12#include "core/core_timing.h" 12#include "core/core_timing.h"
13#include "core/mem_map.h"
14#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
15 14
16#include "core/hle/kernel/address_arbiter.h" 15#include "core/hle/kernel/address_arbiter.h"
17#include "core/hle/kernel/event.h" 16#include "core/hle/kernel/event.h"
17#include "core/hle/kernel/memory.h"
18#include "core/hle/kernel/mutex.h" 18#include "core/hle/kernel/mutex.h"
19#include "core/hle/kernel/process.h" 19#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/resource_limit.h" 20#include "core/hle/kernel/resource_limit.h"
@@ -41,32 +41,114 @@ const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
41const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, 41const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
42 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E 42 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E
43 43
44const ResultCode ERR_MISALIGNED_ADDRESS{ // 0xE0E01BF1
45 ErrorDescription::MisalignedAddress, ErrorModule::OS,
46 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
47const ResultCode ERR_MISALIGNED_SIZE{ // 0xE0E01BF2
48 ErrorDescription::MisalignedSize, ErrorModule::OS,
49 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
50const ResultCode ERR_INVALID_COMBINATION{ // 0xE0E01BEE
51 ErrorDescription::InvalidCombination, ErrorModule::OS,
52 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
53
44enum ControlMemoryOperation { 54enum ControlMemoryOperation {
45 MEMORY_OPERATION_HEAP = 0x00000003, 55 MEMOP_FREE = 1,
46 MEMORY_OPERATION_GSP_HEAP = 0x00010003, 56 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel
57 MEMOP_COMMIT = 3,
58 MEMOP_MAP = 4,
59 MEMOP_UNMAP = 5,
60 MEMOP_PROTECT = 6,
61 MEMOP_OPERATION_MASK = 0xFF,
62
63 MEMOP_REGION_APP = 0x100,
64 MEMOP_REGION_SYSTEM = 0x200,
65 MEMOP_REGION_BASE = 0x300,
66 MEMOP_REGION_MASK = 0xF00,
67
68 MEMOP_LINEAR = 0x10000,
47}; 69};
48 70
49/// Map application or GSP heap memory 71/// Map application or GSP heap memory
50static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 72static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
51 LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 73 using namespace Kernel;
74
75 LOG_DEBUG(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X",
52 operation, addr0, addr1, size, permissions); 76 operation, addr0, addr1, size, permissions);
53 77
54 switch (operation) { 78 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) {
79 return ERR_MISALIGNED_ADDRESS;
80 }
81 if ((size & Memory::PAGE_MASK) != 0) {
82 return ERR_MISALIGNED_SIZE;
83 }
84
85 u32 region = operation & MEMOP_REGION_MASK;
86 operation &= ~MEMOP_REGION_MASK;
87
88 if (region != 0) {
89 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", region);
90 }
91
92 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) {
93 return ERR_INVALID_COMBINATION;
94 }
95 VMAPermission vma_permissions = (VMAPermission)permissions;
96
97 auto& process = *g_current_process;
98
99 switch (operation & MEMOP_OPERATION_MASK) {
100 case MEMOP_FREE:
101 {
102 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) {
103 ResultCode result = process.HeapFree(addr0, size);
104 if (result.IsError()) return result;
105 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) {
106 ResultCode result = process.LinearFree(addr0, size);
107 if (result.IsError()) return result;
108 } else {
109 return ERR_INVALID_ADDRESS;
110 }
111 *out_addr = addr0;
112 break;
113 }
114
115 case MEMOP_COMMIT:
116 {
117 if (operation & MEMOP_LINEAR) {
118 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions));
119 } else {
120 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
121 }
122 break;
123 }
55 124
56 // Map normal heap memory 125 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented
57 case MEMORY_OPERATION_HEAP: 126 {
58 *out_addr = Memory::MapBlock_Heap(size, operation, permissions); 127 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
59 break; 128 break;
129 }
130
131 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented
132 {
133 ResultCode result = process.HeapFree(addr0, size);
134 if (result.IsError()) return result;
135 break;
136 }
60 137
61 // Map GSP heap memory 138 case MEMOP_PROTECT:
62 case MEMORY_OPERATION_GSP_HEAP: 139 {
63 *out_addr = Memory::MapBlock_HeapLinear(size, operation, permissions); 140 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions);
141 if (result.IsError()) return result;
64 break; 142 break;
143 }
65 144
66 // Unknown ControlMemory operation
67 default: 145 default:
68 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation); 146 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation);
147 return ERR_INVALID_COMBINATION;
69 } 148 }
149
150 process.vm_manager.LogLayout(Log::Level::Trace);
151
70 return RESULT_SUCCESS; 152 return RESULT_SUCCESS;
71} 153}
72 154
@@ -537,9 +619,9 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf
537 if (process == nullptr) 619 if (process == nullptr)
538 return ERR_INVALID_HANDLE; 620 return ERR_INVALID_HANDLE;
539 621
540 auto vma = process->address_space->FindVMA(addr); 622 auto vma = process->vm_manager.FindVMA(addr);
541 623
542 if (vma == process->address_space->vma_map.end()) 624 if (vma == Kernel::g_current_process->vm_manager.vma_map.end())
543 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 625 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
544 626
545 memory_info->base_address = vma->second.base; 627 memory_info->base_address = vma->second.base;
@@ -692,6 +774,52 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
692 return RESULT_SUCCESS; 774 return RESULT_SUCCESS;
693} 775}
694 776
777static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
778 LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, type);
779
780 using Kernel::Process;
781 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
782 if (process == nullptr)
783 return ERR_INVALID_HANDLE;
784
785 switch (type) {
786 case 0:
787 case 2:
788 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
789 // what's the difference between them.
790 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
791 break;
792 case 1:
793 case 3:
794 case 4:
795 case 5:
796 case 6:
797 case 7:
798 case 8:
799 // These are valid, but not implemented yet
800 LOG_ERROR(Kernel_SVC, "unimplemented GetProcessInfo type=%u", type);
801 break;
802 case 20:
803 *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase();
804 break;
805 default:
806 LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type);
807
808 if (type >= 21 && type <= 23) {
809 return ResultCode( // 0xE0E01BF4
810 ErrorDescription::NotImplemented, ErrorModule::OS,
811 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
812 } else {
813 return ResultCode( // 0xD8E007ED
814 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
815 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
816 }
817 break;
818 }
819
820 return RESULT_SUCCESS;
821}
822
695namespace { 823namespace {
696 struct FunctionDef { 824 struct FunctionDef {
697 using Func = void(); 825 using Func = void();
@@ -746,7 +874,7 @@ static const FunctionDef SVC_Table[] = {
746 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, 874 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"},
747 {0x29, nullptr, "GetHandleInfo"}, 875 {0x29, nullptr, "GetHandleInfo"},
748 {0x2A, nullptr, "GetSystemInfo"}, 876 {0x2A, nullptr, "GetSystemInfo"},
749 {0x2B, nullptr, "GetProcessInfo"}, 877 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"},
750 {0x2C, nullptr, "GetThreadInfo"}, 878 {0x2C, nullptr, "GetThreadInfo"},
751 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, 879 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"},
752 {0x2E, nullptr, "SendSyncRequest1"}, 880 {0x2E, nullptr, "SendSyncRequest1"},