1 /* 2 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include "precompiled.hpp" 25 #include "gc/shared/gcLogPrecious.hpp" 26 #include "gc/z/zGlobals.hpp" 27 #include "runtime/globals.hpp" 28 #include "utilities/globalDefinitions.hpp" 29 #include "utilities/powerOfTwo.hpp" 30 31 #include <sys/mman.h> 32 33 // 34 // The heap can have three different layouts, depending on the max heap size. 35 // 36 // Address Space & Pointer Layout 1 37 // -------------------------------- 38 // 39 // +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) 40 // . . 41 // . . 42 // . . 43 // +--------------------------------+ 0x0000014000000000 (20TB) 44 // | Remapped View | 45 // +--------------------------------+ 0x0000010000000000 (16TB) 46 // . . 47 // +--------------------------------+ 0x00000c0000000000 (12TB) 48 // | Marked1 View | 49 // +--------------------------------+ 0x0000080000000000 (8TB) 50 // | Marked0 View | 51 // +--------------------------------+ 0x0000040000000000 (4TB) 52 // . . 53 // +--------------------------------+ 0x0000000000000000 54 // 55 // 6 4 4 4 4 56 // 3 6 5 2 1 0 57 // +--------------------+----+-----------------------------------------------+ 58 // |00000000 00000000 00|1111|11 11111111 11111111 11111111 11111111 11111111| 59 // +--------------------+----+-----------------------------------------------+ 60 // | | | 61 // | | * 41-0 Object Offset (42-bits, 4TB address space) 62 // | | 63 // | * 45-42 Metadata Bits (4-bits) 0001 = Marked0 (Address view 4-8TB) 64 // | 0010 = Marked1 (Address view 8-12TB) 65 // | 0100 = Remapped (Address view 16-20TB) 66 // | 1000 = Finalizable (Address view N/A) 67 // | 68 // * 63-46 Fixed (18-bits, always zero) 69 // 70 // 71 // Address Space & Pointer Layout 2 72 // -------------------------------- 73 // 74 // +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) 75 // . . 76 // . . 77 // . . 78 // +--------------------------------+ 0x0000280000000000 (40TB) 79 // | Remapped View | 80 // +--------------------------------+ 0x0000200000000000 (32TB) 81 // . . 82 // +--------------------------------+ 0x0000180000000000 (24TB) 83 // | Marked1 View | 84 // +--------------------------------+ 0x0000100000000000 (16TB) 85 // | Marked0 View | 86 // +--------------------------------+ 0x0000080000000000 (8TB) 87 // . . 88 // +--------------------------------+ 0x0000000000000000 89 // 90 // 6 4 4 4 4 91 // 3 7 6 3 2 0 92 // +------------------+-----+------------------------------------------------+ 93 // |00000000 00000000 0|1111|111 11111111 11111111 11111111 11111111 11111111| 94 // +-------------------+----+------------------------------------------------+ 95 // | | | 96 // | | * 42-0 Object Offset (43-bits, 8TB address space) 97 // | | 98 // | * 46-43 Metadata Bits (4-bits) 0001 = Marked0 (Address view 8-16TB) 99 // | 0010 = Marked1 (Address view 16-24TB) 100 // | 0100 = Remapped (Address view 32-40TB) 101 // | 1000 = Finalizable (Address view N/A) 102 // | 103 // * 63-47 Fixed (17-bits, always zero) 104 // 105 // 106 // Address Space & Pointer Layout 3 107 // -------------------------------- 108 // 109 // +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) 110 // . . 111 // . . 112 // . . 113 // +--------------------------------+ 0x0000500000000000 (80TB) 114 // | Remapped View | 115 // +--------------------------------+ 0x0000400000000000 (64TB) 116 // . . 117 // +--------------------------------+ 0x0000300000000000 (48TB) 118 // | Marked1 View | 119 // +--------------------------------+ 0x0000200000000000 (32TB) 120 // | Marked0 View | 121 // +--------------------------------+ 0x0000100000000000 (16TB) 122 // . . 123 // +--------------------------------+ 0x0000000000000000 124 // 125 // 6 4 4 4 4 126 // 3 8 7 4 3 0 127 // +------------------+----+-------------------------------------------------+ 128 // |00000000 00000000 |1111|1111 11111111 11111111 11111111 11111111 11111111| 129 // +------------------+----+-------------------------------------------------+ 130 // | | | 131 // | | * 43-0 Object Offset (44-bits, 16TB address space) 132 // | | 133 // | * 47-44 Metadata Bits (4-bits) 0001 = Marked0 (Address view 16-32TB) 134 // | 0010 = Marked1 (Address view 32-48TB) 135 // | 0100 = Remapped (Address view 64-80TB) 136 // | 1000 = Finalizable (Address view N/A) 137 // | 138 // * 63-48 Fixed (16-bits, always zero) 139 // 140 141 static size_t probe_valid_max_address_bit() { 142 const size_t page_size = (size_t) sysconf(_SC_PAGE_SIZE); 143 size_t max_address_bits = 0; 144 // TODO: Iterate from high to low addresses and stop at the first valid one, should be faster. 145 for (size_t i = 1; i <= sizeof(uintptr_t) * CHAR_BIT; ++i) { 146 const uintptr_t base_addr = ((uintptr_t) 1U) << i; 147 if (msync((void*)base_addr, page_size, MS_ASYNC) == 0) { 148 // msync suceeded, the address is valid, and maybe even already mapped. 149 max_address_bits = i; 150 continue; 151 } 152 if (errno != ENOMEM) { 153 // Some error occured. This should never happen, but msync 154 // has some undefined behavior, hence ignore this bit. 155 continue; 156 } 157 // Since msync failed with ENOMEM, the page might not be mapped. 158 // Try to map it, to see if the address is valid. 159 void* result_addr = mmap((void*) base_addr, page_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 160 if ((uintptr_t) result_addr == base_addr) { 161 // address is valid 162 max_address_bits = i; 163 } 164 if (result_addr != MAP_FAILED) { 165 munmap(result_addr, page_size); 166 } 167 } 168 max_address_bits += 1; 169 log_info_p(gc, init)("Probing address space for the number of valid bits: %zu", max_address_bits); 170 return max_address_bits; 171 } 172 173 size_t ZPlatformAddressOffsetBits() { 174 const static size_t ZAddressBits = probe_valid_max_address_bit(); 175 const size_t max_address_offset_bits = ZAddressBits - 3; 176 const size_t min_address_offset_bits = max_address_offset_bits - 2; 177 const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); 178 const size_t address_offset_bits = log2_intptr(address_offset); 179 return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); 180 } 181 182 size_t ZPlatformAddressMetadataShift() { 183 return ZPlatformAddressOffsetBits(); 184 }