1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2013-2018. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #ifndef ERL_MMAP_H__
22 #define ERL_MMAP_H__
23 
24 #include "sys.h"
25 #include "erl_printf.h"
26 
27 #define ERTS_MMAP_SUPERALIGNED_BITS (18)
28 /* Affects hard limits for sbct and lmbcs documented in erts_alloc.xml */
29 
30 #ifndef HAVE_MMAP
31 #  define HAVE_MMAP 0
32 #endif
33 #ifndef HAVE_MREMAP
34 #  define HAVE_MREMAP 0
35 #endif
36 #if HAVE_MMAP
37 #  define ERTS_HAVE_OS_MMAP 1
38 #  define ERTS_HAVE_GENUINE_OS_MMAP 1
39 #  if HAVE_MREMAP
40 #    define ERTS_HAVE_OS_MREMAP 1
41 #  endif
42 /*
43  * MAP_NORESERVE is undefined in FreeBSD 10.x and later.
44  * This is to enable 64bit HiPE experimentally on FreeBSD.
45  * Note that on FreeBSD MAP_NORESERVE was "never implemented"
46  * even before 11.x (and the flag does not exist in /usr/src/sys/vm/mmap.c
47  * of 10.3-STABLE r301478 either), and HiPE was working on OTP 18.3.3,
48  * so mandating MAP_NORESERVE on FreeBSD might not be needed.
49  * See the following message on how MAP_NORESERVE was treated on FreeBSD:
50  * <http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20150202/122958.html>
51  */
52 #  if defined(MAP_FIXED) && (defined(MAP_NORESERVE) || defined(__FreeBSD__))
53 #    define ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION 1
54 #  endif
55 #endif
56 
57 #ifndef HAVE_VIRTUALALLOC
58 #  define HAVE_VIRTUALALLOC 0
59 #endif
60 #if HAVE_VIRTUALALLOC
61 #  define ERTS_HAVE_OS_MMAP 1
62 #endif
63 
64 #ifdef ERTS_HAVE_GENUINE_OS_MMAP
65 #  define HAVE_ERTS_MMAP 1
66 #else
67 #  define HAVE_ERTS_MMAP 0
68 #endif
69 
70 
71 extern UWord erts_page_inv_mask;
72 
73 typedef struct {
74     struct {
75 	char *start;
76 	char *end;
77     } virtual_range;
78     struct {
79 	char *start;
80 	char *end;
81     } predefined_area;
82     UWord scs;  /* super carrier size */
83     int sco;    /* super carrier only? */
84     UWord scrfsd; /* super carrier reserved free segment descriptors */
85     int scrpm; /* super carrier reserve physical memory */
86 }ErtsMMapInit;
87 
88 #define ERTS_MMAP_INIT_DEFAULT_INITER \
89     {{NULL, NULL}, {NULL, NULL}, 0, 1, (1 << 16), 1}
90 
91 #define ERTS_LITERAL_VIRTUAL_AREA_SIZE (UWORD_CONSTANT(1)*1024*1024*1024)
92 
93 #define ERTS_MMAP_INIT_LITERAL_INITER \
94     {{NULL, NULL}, {NULL, NULL}, ERTS_LITERAL_VIRTUAL_AREA_SIZE, 1, (1 << 10), 0}
95 
96 
97 #define ERTS_SUPERALIGNED_SIZE \
98     (1 << ERTS_MMAP_SUPERALIGNED_BITS)
99 #define ERTS_INV_SUPERALIGNED_MASK \
100     ((UWord) (ERTS_SUPERALIGNED_SIZE - 1))
101 #define ERTS_SUPERALIGNED_MASK \
102     (~ERTS_INV_SUPERALIGNED_MASK)
103 #define ERTS_SUPERALIGNED_FLOOR(X) \
104     (((UWord) (X)) & ERTS_SUPERALIGNED_MASK)
105 #define ERTS_SUPERALIGNED_CEILING(X) \
106     ERTS_SUPERALIGNED_FLOOR((X) + ERTS_INV_SUPERALIGNED_MASK)
107 #define ERTS_IS_SUPERALIGNED(X) \
108     (((UWord) (X) & ERTS_INV_SUPERALIGNED_MASK) == 0)
109 
110 #define ERTS_INV_PAGEALIGNED_MASK \
111     (erts_page_inv_mask)
112 #define ERTS_PAGEALIGNED_MASK \
113     (~ERTS_INV_PAGEALIGNED_MASK)
114 #define ERTS_PAGEALIGNED_FLOOR(X) \
115     (((UWord) (X)) & ERTS_PAGEALIGNED_MASK)
116 #define ERTS_PAGEALIGNED_CEILING(X) \
117     ERTS_PAGEALIGNED_FLOOR((X) + ERTS_INV_PAGEALIGNED_MASK)
118 #define ERTS_IS_PAGEALIGNED(X) \
119     (((UWord) (X) & ERTS_INV_PAGEALIGNED_MASK) == 0)
120 #define ERTS_PAGEALIGNED_SIZE \
121     (ERTS_INV_PAGEALIGNED_MASK + 1)
122 
123 struct process;
124 Eterm erts_mmap_debug_info(struct process*);
125 
126 #if HAVE_ERTS_MMAP
127 
128 typedef struct ErtsMemMapper_ ErtsMemMapper;
129 
130 #define ERTS_MMAPFLG_OS_ONLY			(((Uint32) 1) << 0)
131 #define ERTS_MMAPFLG_SUPERCARRIER_ONLY		(((Uint32) 1) << 1)
132 #define ERTS_MMAPFLG_SUPERALIGNED		(((Uint32) 1) << 2)
133 
134 void *erts_mmap(ErtsMemMapper*, Uint32 flags, UWord *sizep);
135 void erts_munmap(ErtsMemMapper*, Uint32 flags, void *ptr, UWord size);
136 void *erts_mremap(ErtsMemMapper*, Uint32 flags, void *ptr, UWord old_size, UWord *sizep);
137 int erts_mmap_in_supercarrier(ErtsMemMapper*, void *ptr);
138 void erts_mmap_init(ErtsMemMapper*, ErtsMMapInit*);
139 struct erts_mmap_info_struct
140 {
141     UWord sizes[6];
142     UWord segs[6];
143     UWord os_used;
144 };
145 Eterm erts_mmap_info(ErtsMemMapper*, fmtfn_t *print_to_p, void *print_to_arg,
146                      Eterm** hpp, Uint* szp, struct erts_mmap_info_struct*);
147 Eterm erts_mmap_info_options(ErtsMemMapper*,
148                              char *prefix, fmtfn_t *print_to_p, void *print_to_arg,
149                              Uint **hpp, Uint *szp);
150 
151 
152 #ifdef ERTS_WANT_MEM_MAPPERS
153 #  include "erl_alloc_types.h"
154 
155 extern ErtsMemMapper erts_dflt_mmapper;
156 
157 # if defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
158 
159 #  if defined(ARCH_64)
160 extern ErtsMemMapper erts_literal_mmapper;
161 #  endif
162 
163 # endif /* ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION */
164 #endif /* ERTS_WANT_MEM_MAPPERS */
165 
166 /*#define HARD_DEBUG_MSEG*/
167 #ifdef HARD_DEBUG_MSEG
168 #  define HARD_DBG_INSERT_MSEG hard_dbg_insert_mseg
169 #  define HARD_DBG_REMOVE_MSEG hard_dbg_remove_mseg
170 void hard_dbg_insert_mseg(void* seg, UWord sz);
171 void hard_dbg_remove_mseg(void* seg, UWord sz);
172 #else
173 #  define HARD_DBG_INSERT_MSEG(SEG,SZ)
174 #  define HARD_DBG_REMOVE_MSEG(SEG,SZ)
175 #endif
176 
177 #endif /* HAVE_ERTS_MMAP */
178 
179 #endif /* ERL_MMAP_H__ */
180