* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-#include <linux/mman.h>
-#include <linux/unistd.h>
#include "qemu.h"
#include "qemu-common.h"
-#include "translate-all.h"
//#define DEBUG_MMAP
}
}
+bool have_mmap_lock(void)
+{
+ return mmap_lock_count > 0 ? true : false;
+}
+
/* Grab lock to make sure things are in a consistent state after fork(). */
void mmap_fork_start(void)
{
#endif
if ((start & ~TARGET_PAGE_MASK) != 0)
- return -EINVAL;
+ return -TARGET_EINVAL;
len = TARGET_PAGE_ALIGN(len);
end = start + len;
- if (end < start)
- return -EINVAL;
+ if (!guest_range_valid(start, len)) {
+ return -TARGET_ENOMEM;
+ }
prot &= PROT_READ | PROT_WRITE | PROT_EXEC;
if (len == 0)
return 0;
#if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
# define TASK_UNMAPPED_BASE (1ul << 38)
-#elif defined(__CYGWIN__)
-/* Cygwin doesn't have a whole lot of address space. */
-# define TASK_UNMAPPED_BASE 0x18000000
#else
# define TASK_UNMAPPED_BASE 0x40000000
#endif
if (prot) {
end_addr = addr;
}
- if (addr + size == end_addr) {
+ if (addr && addr + size == end_addr) {
break;
}
addr -= qemu_host_page_size;
}
#endif
- if (offset & ~TARGET_PAGE_MASK) {
+ if (!len) {
errno = EINVAL;
goto fail;
}
+ /* Also check for overflows... */
len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
- goto the_end;
+ if (!len) {
+ errno = ENOMEM;
+ goto fail;
+ }
+
+ if (offset & ~TARGET_PAGE_MASK) {
+ errno = EINVAL;
+ goto fail;
+ }
+
real_start = start & qemu_host_page_mask;
host_offset = offset & qemu_host_page_mask;
may need to truncate file maps at EOF and add extra anonymous pages
up to the targets page boundary. */
- if ((qemu_real_host_page_size < TARGET_PAGE_SIZE)
- && !(flags & MAP_ANONYMOUS)) {
- struct stat sb;
+ if ((qemu_real_host_page_size < qemu_host_page_size) &&
+ !(flags & MAP_ANONYMOUS)) {
+ struct stat sb;
if (fstat (fd, &sb) == -1)
goto fail;
* It can fail only on 64-bit host with 32-bit target.
* On any other target/host host mmap() handles this error correctly.
*/
- if ((unsigned long)start + len - 1 > (abi_ulong) -1) {
- errno = EINVAL;
+ if (!guest_range_valid(start, len)) {
+ errno = ENOMEM;
goto fail;
}
start, len);
#endif
if (start & ~TARGET_PAGE_MASK)
- return -EINVAL;
+ return -TARGET_EINVAL;
len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
- return -EINVAL;
+ if (len == 0 || !guest_range_valid(start, len)) {
+ return -TARGET_EINVAL;
+ }
+
mmap_lock();
end = start + len;
real_start = start & qemu_host_page_mask;
int prot;
void *host_addr;
+ if (!guest_range_valid(old_addr, old_size) ||
+ ((flags & MREMAP_FIXED) &&
+ !guest_range_valid(new_addr, new_size))) {
+ errno = ENOMEM;
+ return -1;
+ }
+
mmap_lock();
if (flags & MREMAP_FIXED) {
- host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
- old_size, new_size,
- flags,
- g2h(new_addr));
+ host_addr = mremap(g2h(old_addr), old_size, new_size,
+ flags, g2h(new_addr));
if (reserved_va && host_addr != MAP_FAILED) {
/* If new and old addresses overlap then the above mremap will
errno = ENOMEM;
host_addr = MAP_FAILED;
} else {
- host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
- old_size, new_size,
- flags | MREMAP_FIXED,
- g2h(mmap_start));
+ host_addr = mremap(g2h(old_addr), old_size, new_size,
+ flags | MREMAP_FIXED, g2h(mmap_start));
if (reserved_va) {
mmap_reserve(old_addr, old_size);
}
mmap_unlock();
return new_addr;
}
-
-int target_msync(abi_ulong start, abi_ulong len, int flags)
-{
- abi_ulong end;
-
- if (start & ~TARGET_PAGE_MASK)
- return -EINVAL;
- len = TARGET_PAGE_ALIGN(len);
- end = start + len;
- if (end < start)
- return -EINVAL;
- if (end == start)
- return 0;
-
- start &= qemu_host_page_mask;
- return msync(g2h(start), end - start, flags);
-}