db661b6d941c6ce6adaea4d009fbad9f71b59ca4
[pcsx_rearmed.git] / frontend / linux / plat_mmap.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2008-2010
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
6  *  - GNU GPL, version 2 or later.
7  *  - GNU LGPL, version 2.1 or later.
8  * See the COPYING file in the top-level directory.
9  */
10
11 #define _GNU_SOURCE 1
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdarg.h>
15 #include <unistd.h>
16 #include <sys/mman.h>
17 #include <errno.h>
18
19 // this is some dupe code to avoid libpicofe dep
20
21 //#include "../libpicofe/plat.h"
22
23 /* XXX: maybe unhardcode pagesize? */
24 #define HUGETLB_PAGESIZE (2 * 1024 * 1024)
25 #define HUGETLB_THRESHOLD (HUGETLB_PAGESIZE / 2)
26 #ifndef MAP_HUGETLB
27 #define MAP_HUGETLB 0x40000 /* arch specific */
28 #endif
29
30 void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
31 {
32         static int hugetlb_disabled;
33         int prot = PROT_READ | PROT_WRITE;
34         int flags = MAP_PRIVATE | MAP_ANONYMOUS;
35         void *req, *ret;
36
37         req = (void *)addr;
38         if (need_exec)
39                 prot |= PROT_EXEC;
40         if (is_fixed)
41                 flags |= MAP_FIXED;
42         if (size >= HUGETLB_THRESHOLD && !hugetlb_disabled)
43                 flags |= MAP_HUGETLB;
44
45         ret = mmap(req, size, prot, flags, -1, 0);
46         if (ret == MAP_FAILED && (flags & MAP_HUGETLB)) {
47                 fprintf(stderr,
48                         "warning: failed to do hugetlb mmap (%p, %zu): %d\n",
49                         req, size, errno);
50                 hugetlb_disabled = 1;
51                 flags &= ~MAP_HUGETLB;
52                 ret = mmap(req, size, prot, flags, -1, 0);
53         }
54         if (ret == MAP_FAILED)
55                 return NULL;
56
57         if (req != NULL && ret != req)
58                 fprintf(stderr,
59                         "warning: mmaped to %p, requested %p\n", ret, req);
60
61         return ret;
62 }
63
64 void *plat_mremap(void *ptr, size_t oldsize, size_t newsize)
65 {
66         void *ret;
67
68         ret = mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE);
69         if (ret == MAP_FAILED)
70                 return NULL;
71         if (ret != ptr)
72                 printf("warning: mremap moved: %p -> %p\n", ptr, ret);
73
74         return ret;
75 }
76
77 void plat_munmap(void *ptr, size_t size)
78 {
79         int ret;
80
81         ret = munmap(ptr, size);
82         if (ret != 0 && (size & (HUGETLB_PAGESIZE - 1))) {
83                 // prehaps an autorounded hugetlb mapping?
84                 size = (size + HUGETLB_PAGESIZE - 1) & ~(HUGETLB_PAGESIZE - 1);
85                 ret = munmap(ptr, size);
86         }
87         if (ret != 0) {
88                 fprintf(stderr,
89                         "munmap(%p, %zu) failed: %d\n", ptr, size, errno);
90         }
91 }