| 38 | } |
| 39 | |
| 40 | error_code sys_vm_memory_map(ppu_thread &ppu, u64 vsize, u64 psize, u32 cid, |
| 41 | u64 flag, u64 policy, vm::ptr<u32> addr) { |
| 42 | ppu.state += cpu_flag::wait; |
| 43 | |
| 44 | sys_vm.warning("sys_vm_memory_map(vsize=0x%x, psize=0x%x, cid=0x%x, " |
| 45 | "flags=0x%x, policy=0x%x, addr=*0x%x)", |
| 46 | vsize, psize, cid, flag, policy, addr); |
| 47 | |
| 48 | if (!vsize || !psize || vsize % 0x200'0000 || vsize > 0x1000'0000 || |
| 49 | psize % 0x1'0000 || policy != SYS_VM_POLICY_AUTO_RECOMMENDED) { |
| 50 | return CELL_EINVAL; |
| 51 | } |
| 52 | |
| 53 | if (ppu.gpr[11] == 300 && psize < 0x10'0000) { |
| 54 | return CELL_EINVAL; |
| 55 | } |
| 56 | |
| 57 | const auto idm_ct = idm::get_unlocked<lv2_memory_container>(cid); |
| 58 | |
| 59 | const auto ct = cid == SYS_MEMORY_CONTAINER_ID_INVALID |
| 60 | ? &g_fxo->get<lv2_memory_container>() |
| 61 | : idm_ct.get(); |
| 62 | |
| 63 | if (!ct) { |
| 64 | return CELL_ESRCH; |
| 65 | } |
| 66 | |
| 67 | if (!g_fxo->get<sys_vm_global_t>() |
| 68 | .total_vsize |
| 69 | .fetch_op([vsize, has_root = g_ps3_process_info.has_root_perm()]( |
| 70 | u32 &size) { |
| 71 | // A single process can hold up to 256MB of virtual memory, even on |
| 72 | // DECR |
| 73 | // VSH can hold more |
| 74 | if ((has_root ? 0x1E000000 : 0x10000000) - size < vsize) { |
| 75 | return false; |
| 76 | } |
| 77 | |
| 78 | size += static_cast<u32>(vsize); |
| 79 | return true; |
| 80 | }) |
| 81 | .second) { |
| 82 | return CELL_EBUSY; |
| 83 | } |
| 84 | |
| 85 | if (!ct->take(psize)) { |
| 86 | g_fxo->get<sys_vm_global_t>().total_vsize -= static_cast<u32>(vsize); |
| 87 | return CELL_ENOMEM; |
| 88 | } |
| 89 | |
| 90 | // Look for unmapped space |
| 91 | if (const auto area = vm::find_map(0x10000000, 0x10000000, |
| 92 | 2 | (flag & SYS_MEMORY_PAGE_SIZE_MASK))) { |
| 93 | sys_vm.warning("sys_vm_memory_map(): Found VM 0x%x area (vsize=0x%x)", addr, |
| 94 | vsize); |
| 95 | |
| 96 | // Alloc all memory (shall not fail) |
| 97 | ensure(area->alloc(static_cast<u32>(vsize))); |
no test coverage detected