698517be |
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 | |
7badc935 |
11 | #define _GNU_SOURCE 1 |
698517be |
12 | #include <stdio.h> |
13 | #include <string.h> |
14 | #include <stdarg.h> |
698517be |
15 | #include <unistd.h> |
16 | #include <sys/mman.h> |
9ee0fd5b |
17 | #include <errno.h> |
698517be |
18 | |
cc56203b |
19 | // this is some dupe code to avoid libpicofe dep |
20 | |
21 | //#include "../libpicofe/plat.h" |
698517be |
22 | |
9ee0fd5b |
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 | |
a2ad8cc5 |
30 | void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) |
698517be |
31 | { |
9ee0fd5b |
32 | static int hugetlb_disabled; |
33 | int prot = PROT_READ | PROT_WRITE; |
34 | int flags = MAP_PRIVATE | MAP_ANONYMOUS; |
698517be |
35 | void *req, *ret; |
36 | |
37 | req = (void *)addr; |
9ee0fd5b |
38 | if (need_exec) |
39 | prot |= PROT_EXEC; |
a2ad8cc5 |
40 | if (is_fixed) |
41 | flags |= MAP_FIXED; |
9ee0fd5b |
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 | } |
698517be |
54 | if (ret == MAP_FAILED) |
55 | return NULL; |
9ee0fd5b |
56 | |
57 | if (req != NULL && ret != req) |
58 | fprintf(stderr, |
59 | "warning: mmaped to %p, requested %p\n", ret, req); |
698517be |
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 | { |
9ee0fd5b |
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 | } |
698517be |
91 | } |