summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-07-17 23:19:16 -0300
committerGravatar Yuri Kunde Schlesner2015-08-16 01:03:45 -0300
commitcdeeecf0807d0005356f30db0f7164c5891a9245 (patch)
treee32e6d673cdac358df0abd3d3ece13f37c1c28d5 /src/core/hle/svc.cpp
parentMemory: Move PAGE_MASK and PAGE_BITS to memory.h (diff)
downloadyuzu-cdeeecf0807d0005356f30db0f7164c5891a9245.tar.gz
yuzu-cdeeecf0807d0005356f30db0f7164c5891a9245.tar.xz
yuzu-cdeeecf0807d0005356f30db0f7164c5891a9245.zip
Kernel: Properly implement ControlMemory FREE and COMMIT
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp108
1 files changed, 95 insertions, 13 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index bb64fdfb7..91260fe71 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -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 }
55 91
56 // Map normal heap memory 92 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) {
57 case MEMORY_OPERATION_HEAP: 93 return ERR_INVALID_COMBINATION;
58 *out_addr = Memory::MapBlock_Heap(size, operation, permissions); 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 >= Memory::LINEAR_HEAP_VADDR && addr0 < Memory::LINEAR_HEAP_VADDR_END) {
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;
59 break; 112 break;
113 }
60 114
61 // Map GSP heap memory 115 case MEMOP_COMMIT:
62 case MEMORY_OPERATION_GSP_HEAP: 116 {
63 *out_addr = Memory::MapBlock_HeapLinear(size, operation, permissions); 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 }
64 break; 122 break;
123 }
124
125 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented
126 {
127 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
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 }
137
138 case MEMOP_PROTECT:
139 {
140 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions);
141 if (result.IsError()) return result;
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;