| 65 | } |
| 66 | |
| 67 | U32 KMemory::mmap(KThread* thread, U32 addr, U32 len, S32 prot, S32 flags, FD fildes, U64 off, bool remap) { |
| 68 | bool shared = (flags & K_MAP_SHARED) != 0; |
| 69 | bool priv = (flags & K_MAP_PRIVATE) != 0; |
| 70 | bool read = (prot & K_PROT_READ) != 0; |
| 71 | bool write = (prot & K_PROT_WRITE) != 0; |
| 72 | bool exec = (prot & K_PROT_EXEC) != 0; |
| 73 | U32 pageStart = addr >> K_PAGE_SHIFT; |
| 74 | U32 pageCount = (len + K_PAGE_SIZE - 1) >> K_PAGE_SHIFT; |
| 75 | KFileDescriptorPtr fd; |
| 76 | |
| 77 | if (0xFFFFFFFF - addr < len) { |
| 78 | return -K_EINVAL; |
| 79 | } |
| 80 | if ((shared && priv) || (!shared && !priv)) { |
| 81 | return -K_EINVAL; |
| 82 | } |
| 83 | |
| 84 | if (!(flags & K_MAP_ANONYMOUS) && fildes >= 0) { |
| 85 | fd = this->process->getFileDescriptor(fildes); |
| 86 | if (!fd) { |
| 87 | return -K_EBADF; |
| 88 | } |
| 89 | if (!fd->kobject->canMap()) { |
| 90 | return -K_EACCES; |
| 91 | } |
| 92 | if (len == 0 || (off & 0xFFF) != 0) { |
| 93 | return -K_EINVAL; |
| 94 | } |
| 95 | if ((!fd->canRead() && read) || (!priv && (!fd->canWrite() && write))) { |
| 96 | return -K_EACCES; |
| 97 | } |
| 98 | } |
| 99 | BOXEDWINE_CRITICAL_SECTION_WITH_MUTEX(mutex); |
| 100 | if (flags & (K_MAP_FIXED | K_MAP_FIXED_NOREPLACE)) { |
| 101 | if (addr & (K_PAGE_SIZE - 1)) { |
| 102 | klog_fmt("tried to call mmap with invalid address: %X", addr); |
| 103 | return -K_EINVAL; |
| 104 | } |
| 105 | if (flags & K_MAP_FIXED_NOREPLACE) { |
| 106 | if (!remap && addr != 0 && pageStart + pageCount > ADDRESS_PROCESS_MMAP_START) { |
| 107 | return -K_ENOMEM; |
| 108 | } |
| 109 | for (U32 page = pageStart; page < pageStart + pageCount; page++) { |
| 110 | if (isPageMapped(page)) { |
| 111 | return -K_EEXIST; |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | } else { |
| 116 | if (pageStart + pageCount > ADDRESS_PROCESS_MMAP_START) { |
| 117 | return -K_ENOMEM; |
| 118 | } |
| 119 | if (pageStart == 0) { |
| 120 | // :TODO: this seems like a hack, there must be something wrong with how I implemented mmap |
| 121 | if (KSystem::wineMajorVersion >= 7 && (flags & K_MAP_BOXEDWINE) == 0) { |
| 122 | pageStart = 0x10000; |
| 123 | } else { |
| 124 | pageStart = ADDRESS_PROCESS_MMAP_START; |