OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // Author: Ken Chen <kenchen@google.com> | 4 // Author: Ken Chen <kenchen@google.com> |
5 // | 5 // |
6 // hugepage text library to remap process executable segment with hugepages. | 6 // hugepage text library to remap process executable segment with hugepages. |
7 | 7 |
8 #include "chromeos/hugepage_text/hugepage_text.h" | 8 #include "chromeos/hugepage_text/hugepage_text.h" |
9 | 9 |
10 #include <link.h> | 10 #include <link.h> |
(...skipping 18 matching lines...) Expand all Loading... |
29 | 29 |
30 const int kHpageShift = 21; | 30 const int kHpageShift = 21; |
31 const int kHpageSize = (1 << kHpageShift); | 31 const int kHpageSize = (1 << kHpageShift); |
32 const int kHpageMask = (~(kHpageSize - 1)); | 32 const int kHpageMask = (~(kHpageSize - 1)); |
33 | 33 |
34 const int kProtection = (PROT_READ | PROT_WRITE); | 34 const int kProtection = (PROT_READ | PROT_WRITE); |
35 const int kMmapFlags = (MAP_ANONYMOUS | MAP_SHARED); | 35 const int kMmapFlags = (MAP_ANONYMOUS | MAP_SHARED); |
36 const int kMmapHtlbFlags = (kMmapFlags | MAP_HUGETLB); | 36 const int kMmapHtlbFlags = (kMmapFlags | MAP_HUGETLB); |
37 const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED); | 37 const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED); |
38 | 38 |
| 39 // The number of hugepages we want to use to map chrome text section |
| 40 // to hugepages. With the help of AutoFDO, the hot functions are grouped |
| 41 // in to a small area of the binary. |
| 42 const int kNumHugePages = 15; |
| 43 |
39 // mremap syscall is always supported for small page segment on all kernels. | 44 // mremap syscall is always supported for small page segment on all kernels. |
40 // However, it is not the case for hugepage. | 45 // However, it is not the case for hugepage. |
41 // If not used carefully, mremap() a hugepage segment directly onto small page | 46 // If not used carefully, mremap() a hugepage segment directly onto small page |
42 // text segment will cause irreversible damage to the existing text mapping | 47 // text segment will cause irreversible damage to the existing text mapping |
43 // and cause process to segfault. This function will dynamically at run time | 48 // and cause process to segfault. This function will dynamically at run time |
44 // determine whether a process can safely execute mremap on a hugepage segment | 49 // determine whether a process can safely execute mremap on a hugepage segment |
45 // without taking the process down. | 50 // without taking the process down. |
46 // | 51 // |
47 // Inputs: none | 52 // Inputs: none |
48 // Return: true if mremap on hugepage segment is supported on the host OS. | 53 // Return: true if mremap on hugepage segment is supported on the host OS. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 // Remaps text segment at address "vaddr" to hugepage backed mapping via mremap | 122 // Remaps text segment at address "vaddr" to hugepage backed mapping via mremap |
118 // syscall. The virtual address does not change. When this call returns, the | 123 // syscall. The virtual address does not change. When this call returns, the |
119 // backing physical memory will be changed from small page to hugetlb page. | 124 // backing physical memory will be changed from small page to hugetlb page. |
120 // | 125 // |
121 // Inputs: vaddr, the starting virtual address to remap to hugepage | 126 // Inputs: vaddr, the starting virtual address to remap to hugepage |
122 // hsize, size of the memory segment to remap in bytes | 127 // hsize, size of the memory segment to remap in bytes |
123 // Return: none | 128 // Return: none |
124 // Effect: physical backing page changed from small page to hugepage. If there | 129 // Effect: physical backing page changed from small page to hugepage. If there |
125 // are error condition, the remapping operation is aborted. | 130 // are error condition, the remapping operation is aborted. |
126 static void MremapHugetlbText(void* vaddr, const size_t hsize) { | 131 static void MremapHugetlbText(void* vaddr, const size_t hsize) { |
127 DCHECK_EQ(0ul, reinterpret_cast<uintptr_t>(vaddr) & ~kHpageMask); | |
128 void* haddr = MAP_FAILED; | 132 void* haddr = MAP_FAILED; |
129 if (HugetlbMremapSupported()) { | 133 |
| 134 if ((reinterpret_cast<intptr_t>(vaddr) & ~kHpageMask) == 0 && |
| 135 HugetlbMremapSupported()) { |
130 // Try anon hugepage from static hugepage pool only if the source address | 136 // Try anon hugepage from static hugepage pool only if the source address |
131 // is hugepage aligned, otherwise, mremap below has non-recoverable error. | 137 // is hugepage aligned, otherwise, mremap below has non-recoverable error. |
132 haddr = mmap(NULL, hsize, kProtection, kMmapHtlbFlags, 0, 0); | 138 haddr = mmap(NULL, hsize, kProtection, kMmapHtlbFlags, 0, 0); |
133 } | 139 } |
134 | 140 |
135 if (haddr == MAP_FAILED) { | 141 if (haddr == MAP_FAILED) { |
136 PLOG(INFO) << "static hugepage not available, trying transparent hugepage"; | 142 PLOG(INFO) << "static hugepage not available, trying transparent hugepage"; |
137 haddr = GetTransparentHugepageMapping(hsize); | 143 haddr = GetTransparentHugepageMapping(hsize); |
138 if (haddr == NULL) | 144 if (haddr == NULL) |
139 return; | 145 return; |
(...skipping 19 matching lines...) Expand all Loading... |
159 } | 165 } |
160 | 166 |
161 // Top level text remapping function. | 167 // Top level text remapping function. |
162 // | 168 // |
163 // Inputs: vaddr, the starting virtual address to remap to hugepage | 169 // Inputs: vaddr, the starting virtual address to remap to hugepage |
164 // hsize, size of the memory segment to remap in bytes | 170 // hsize, size of the memory segment to remap in bytes |
165 // Return: none | 171 // Return: none |
166 // Effect: physical backing page changed from small page to hugepage. If there | 172 // Effect: physical backing page changed from small page to hugepage. If there |
167 // are error condition, the remaping operation is aborted. | 173 // are error condition, the remaping operation is aborted. |
168 static void RemapHugetlbText(void* vaddr, const size_t segsize) { | 174 static void RemapHugetlbText(void* vaddr, const size_t segsize) { |
169 // remove unaligned head regions | 175 int hsize = segsize; |
170 size_t head_gap = (kHpageSize - reinterpret_cast<size_t>(vaddr) % kHpageSize) | 176 if (segsize > kHpageSize * kNumHugePages) |
171 % kHpageSize; | 177 hsize = kHpageSize * kNumHugePages; |
172 size_t addr = reinterpret_cast<size_t>(vaddr) + head_gap; | |
173 | |
174 int hsize = segsize - head_gap; | |
175 hsize = hsize & kHpageMask; | 178 hsize = hsize & kHpageMask; |
176 | 179 |
177 if (hsize == 0) | 180 if (hsize == 0) |
178 return; | 181 return; |
179 | 182 |
180 MremapHugetlbText(reinterpret_cast<void *>(addr), hsize); | 183 MremapHugetlbText(vaddr, hsize); |
181 } | 184 } |
182 | 185 |
183 // For a given ELF program header descriptor, iterates over all segments within | 186 // For a given ELF program header descriptor, iterates over all segments within |
184 // it and find the first segment that has PT_LOAD and is executable, call | 187 // it and find the first segment that has PT_LOAD and is executable, call |
185 // RemapHugetlbText(). | 188 // RemapHugetlbText(). |
186 // | 189 // |
187 // Inputs: info: pointer to a struct dl_phdr_info that describes the DSO. | 190 // Inputs: info: pointer to a struct dl_phdr_info that describes the DSO. |
188 // size: size of the above structure (not used in this function). | 191 // size: size of the above structure (not used in this function). |
189 // data: user param (not used in this function). | 192 // data: user param (not used in this function). |
190 // Return: always return true. The value is propagated by dl_iterate_phdr(). | 193 // Return: always return true. The value is propagated by dl_iterate_phdr(). |
(...skipping 18 matching lines...) Expand all Loading... |
209 | 212 |
210 // Main library function. This function will iterate all ELF segments and | 213 // Main library function. This function will iterate all ELF segments and |
211 // attempt to remap text segment from small page to hugepage. | 214 // attempt to remap text segment from small page to hugepage. |
212 // If remapping is successful. All error conditions are soft fail such that | 215 // If remapping is successful. All error conditions are soft fail such that |
213 // effect will be rolled back and remap operation will be aborted. | 216 // effect will be rolled back and remap operation will be aborted. |
214 void ReloadElfTextInHugePages(void) { | 217 void ReloadElfTextInHugePages(void) { |
215 dl_iterate_phdr(FilterElfHeader, 0); | 218 dl_iterate_phdr(FilterElfHeader, 0); |
216 } | 219 } |
217 | 220 |
218 } // namespace chromeos | 221 } // namespace chromeos |
OLD | NEW |