Chromium Code Reviews| 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 | |
| 44 // mremap syscall is always supported for small page segment on all kernels. | 39 // mremap syscall is always supported for small page segment on all kernels. |
| 45 // However, it is not the case for hugepage. | 40 // However, it is not the case for hugepage. |
| 46 // If not used carefully, mremap() a hugepage segment directly onto small page | 41 // If not used carefully, mremap() a hugepage segment directly onto small page |
| 47 // text segment will cause irreversible damage to the existing text mapping | 42 // text segment will cause irreversible damage to the existing text mapping |
| 48 // and cause process to segfault. This function will dynamically at run time | 43 // and cause process to segfault. This function will dynamically at run time |
| 49 // determine whether a process can safely execute mremap on a hugepage segment | 44 // determine whether a process can safely execute mremap on a hugepage segment |
| 50 // without taking the process down. | 45 // without taking the process down. |
| 51 // | 46 // |
| 52 // Inputs: none | 47 // Inputs: none |
| 53 // Return: true if mremap on hugepage segment is supported on the host OS. | 48 // Return: true if mremap on hugepage segment is supported on the host OS. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 // backing physical memory will be changed from small page to hugetlb page. | 119 // backing physical memory will be changed from small page to hugetlb page. |
| 125 // | 120 // |
| 126 // Inputs: vaddr, the starting virtual address to remap to hugepage | 121 // Inputs: vaddr, the starting virtual address to remap to hugepage |
| 127 // hsize, size of the memory segment to remap in bytes | 122 // hsize, size of the memory segment to remap in bytes |
| 128 // Return: none | 123 // Return: none |
| 129 // Effect: physical backing page changed from small page to hugepage. If there | 124 // Effect: physical backing page changed from small page to hugepage. If there |
| 130 // are error condition, the remapping operation is aborted. | 125 // are error condition, the remapping operation is aborted. |
| 131 static void MremapHugetlbText(void* vaddr, const size_t hsize) { | 126 static void MremapHugetlbText(void* vaddr, const size_t hsize) { |
| 132 void* haddr = MAP_FAILED; | 127 void* haddr = MAP_FAILED; |
| 133 | 128 |
| 134 if ((reinterpret_cast<intptr_t>(vaddr) & ~kHpageMask) == 0 && | 129 if ((reinterpret_cast<intptr_t>(vaddr) & ~kHpageMask) == 0 && |
|
rickyz (no longer on Chrome)
2016/02/03 21:01:31
You can probably just DCHECK_EQ(0, reinterpret_cas
yunlian
2016/02/03 21:21:51
What is the difference between the expression and
rickyz (no longer on Chrome)
2016/02/03 21:28:24
On debug builds, DCHECK would cause a crash if the
yunlian
2016/02/03 21:34:57
Done.
| |
| 135 HugetlbMremapSupported()) { | 130 HugetlbMremapSupported()) { |
| 136 // Try anon hugepage from static hugepage pool only if the source address | 131 // Try anon hugepage from static hugepage pool only if the source address |
| 137 // is hugepage aligned, otherwise, mremap below has non-recoverable error. | 132 // is hugepage aligned, otherwise, mremap below has non-recoverable error. |
| 138 haddr = mmap(NULL, hsize, kProtection, kMmapHtlbFlags, 0, 0); | 133 haddr = mmap(NULL, hsize, kProtection, kMmapHtlbFlags, 0, 0); |
| 139 } | 134 } |
| 140 | 135 |
| 141 if (haddr == MAP_FAILED) { | 136 if (haddr == MAP_FAILED) { |
| 142 PLOG(INFO) << "static hugepage not available, trying transparent hugepage"; | 137 PLOG(INFO) << "static hugepage not available, trying transparent hugepage"; |
| 143 haddr = GetTransparentHugepageMapping(hsize); | 138 haddr = GetTransparentHugepageMapping(hsize); |
| 144 if (haddr == NULL) | 139 if (haddr == NULL) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 165 } | 160 } |
| 166 | 161 |
| 167 // Top level text remapping function. | 162 // Top level text remapping function. |
| 168 // | 163 // |
| 169 // Inputs: vaddr, the starting virtual address to remap to hugepage | 164 // Inputs: vaddr, the starting virtual address to remap to hugepage |
| 170 // hsize, size of the memory segment to remap in bytes | 165 // hsize, size of the memory segment to remap in bytes |
| 171 // Return: none | 166 // Return: none |
| 172 // Effect: physical backing page changed from small page to hugepage. If there | 167 // Effect: physical backing page changed from small page to hugepage. If there |
| 173 // are error condition, the remaping operation is aborted. | 168 // are error condition, the remaping operation is aborted. |
| 174 static void RemapHugetlbText(void* vaddr, const size_t segsize) { | 169 static void RemapHugetlbText(void* vaddr, const size_t segsize) { |
| 175 int hsize = segsize; | 170 // remove unaligned head regions |
| 176 if (segsize > kHpageSize * kNumHugePages) | 171 size_t head_gap = (kHpageSize - static_cast<size_t>(vaddr) % kHpageSize) |
| 177 hsize = kHpageSize * kNumHugePages; | 172 % kHpageSize; |
| 173 size_t addr = static_cast<size_t>(vaddr) + head_gap; | |
| 174 | |
| 175 int hsize = segsize - head_gap; | |
| 178 hsize = hsize & kHpageMask; | 176 hsize = hsize & kHpageMask; |
| 179 | 177 |
| 180 if (hsize == 0) | 178 if (hsize == 0) |
| 181 return; | 179 return; |
| 182 | 180 |
| 183 MremapHugetlbText(vaddr, hsize); | 181 MremapHugetlbText(static_cast<void *>(addr), hsize); |
| 184 } | 182 } |
| 185 | 183 |
| 186 // For a given ELF program header descriptor, iterates over all segments within | 184 // For a given ELF program header descriptor, iterates over all segments within |
| 187 // it and find the first segment that has PT_LOAD and is executable, call | 185 // it and find the first segment that has PT_LOAD and is executable, call |
| 188 // RemapHugetlbText(). | 186 // RemapHugetlbText(). |
| 189 // | 187 // |
| 190 // Inputs: info: pointer to a struct dl_phdr_info that describes the DSO. | 188 // Inputs: info: pointer to a struct dl_phdr_info that describes the DSO. |
| 191 // size: size of the above structure (not used in this function). | 189 // size: size of the above structure (not used in this function). |
| 192 // data: user param (not used in this function). | 190 // data: user param (not used in this function). |
| 193 // Return: always return true. The value is propagated by dl_iterate_phdr(). | 191 // Return: always return true. The value is propagated by dl_iterate_phdr(). |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 212 | 210 |
| 213 // Main library function. This function will iterate all ELF segments and | 211 // Main library function. This function will iterate all ELF segments and |
| 214 // attempt to remap text segment from small page to hugepage. | 212 // attempt to remap text segment from small page to hugepage. |
| 215 // If remapping is successful. All error conditions are soft fail such that | 213 // If remapping is successful. All error conditions are soft fail such that |
| 216 // effect will be rolled back and remap operation will be aborted. | 214 // effect will be rolled back and remap operation will be aborted. |
| 217 void ReloadElfTextInHugePages(void) { | 215 void ReloadElfTextInHugePages(void) { |
| 218 dl_iterate_phdr(FilterElfHeader, 0); | 216 dl_iterate_phdr(FilterElfHeader, 0); |
| 219 } | 217 } |
| 220 | 218 |
| 221 } // namespace chromeos | 219 } // namespace chromeos |
| OLD | NEW |