Path: blob/master/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp
66645 views
/*1* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "gc/shared/gcLogPrecious.hpp"25#include "gc/z/zErrno.hpp"26#include "gc/z/zGlobals.hpp"27#include "gc/z/zLargePages.inline.hpp"28#include "gc/z/zPhysicalMemory.inline.hpp"29#include "gc/z/zPhysicalMemoryBacking_bsd.hpp"30#include "logging/log.hpp"31#include "runtime/globals.hpp"32#include "runtime/os.hpp"33#include "utilities/align.hpp"34#include "utilities/debug.hpp"3536#include <TargetConditionals.h>37#include <mach/mach.h>38#if TARGET_OS_IPHONE39extern "C" kern_return_t mach_vm_remap(vm_map_t target_task,40mach_vm_address_t *target_address,41mach_vm_size_t size,42mach_vm_offset_t mask,43int flags,44vm_map_t src_task,45mach_vm_address_t src_address,46boolean_t copy,47vm_prot_t *cur_protection,48vm_prot_t *max_protection,49vm_inherit_t inheritance);50#else51#include <mach/mach_vm.h>52#endif53#include <sys/mman.h>54#include <sys/types.h>5556// The backing is represented by a reserved virtual address space, in which57// we commit and uncommit physical memory. Multi-mapping the different heap58// views is done by simply remapping the backing memory using mach_vm_remap().5960static int vm_flags_superpage() {61if (!ZLargePages::is_explicit()) {62return 0;63}6465const int page_size_in_megabytes = ZGranuleSize >> 20;66return page_size_in_megabytes << VM_FLAGS_SUPERPAGE_SHIFT;67}6869static ZErrno mremap(uintptr_t from_addr, uintptr_t to_addr, size_t size) {70mach_vm_address_t remap_addr = to_addr;71vm_prot_t remap_cur_prot;72vm_prot_t remap_max_prot;7374// Remap memory to an additional location75const kern_return_t res = mach_vm_remap(mach_task_self(),76&remap_addr,77size,780 /* mask */,79VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE | vm_flags_superpage(),80mach_task_self(),81from_addr,82FALSE /* copy */,83&remap_cur_prot,84&remap_max_prot,85VM_INHERIT_COPY);8687return (res == KERN_SUCCESS) ? ZErrno(0) : ZErrno(EINVAL);88}8990ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) :91_base(0),92_initialized(false) {9394// Reserve address space for backing memory95_base = (uintptr_t)os::reserve_memory(max_capacity);96if (_base == 0) {97// Failed98log_error_pd(gc)("Failed to reserve address space for backing memory");99return;100}101102// Successfully initialized103_initialized = true;104}105106bool ZPhysicalMemoryBacking::is_initialized() const {107return _initialized;108}109110void ZPhysicalMemoryBacking::warn_commit_limits(size_t max_capacity) const {111// Does nothing112}113114bool ZPhysicalMemoryBacking::commit_inner(size_t offset, size_t length) const {115assert(is_aligned(offset, os::vm_page_size()), "Invalid offset");116assert(is_aligned(length, os::vm_page_size()), "Invalid length");117118log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",119offset / M, (offset + length) / M, length / M);120121const uintptr_t addr = _base + offset;122const void* const res = mmap((void*)addr, length, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);123if (res == MAP_FAILED) {124ZErrno err;125log_error(gc)("Failed to commit memory (%s)", err.to_string());126return false;127}128129// Success130return true;131}132133size_t ZPhysicalMemoryBacking::commit(size_t offset, size_t length) const {134// Try to commit the whole region135if (commit_inner(offset, length)) {136// Success137return length;138}139140// Failed, try to commit as much as possible141size_t start = offset;142size_t end = offset + length;143144for (;;) {145length = align_down((end - start) / 2, ZGranuleSize);146if (length == 0) {147// Done, don't commit more148return start - offset;149}150151if (commit_inner(start, length)) {152// Success, try commit more153start += length;154} else {155// Failed, try commit less156end -= length;157}158}159}160161size_t ZPhysicalMemoryBacking::uncommit(size_t offset, size_t length) const {162assert(is_aligned(offset, os::vm_page_size()), "Invalid offset");163assert(is_aligned(length, os::vm_page_size()), "Invalid length");164165log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",166offset / M, (offset + length) / M, length / M);167168const uintptr_t start = _base + offset;169const void* const res = mmap((void*)start, length, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);170if (res == MAP_FAILED) {171ZErrno err;172log_error(gc)("Failed to uncommit memory (%s)", err.to_string());173return 0;174}175176return length;177}178179void ZPhysicalMemoryBacking::map(uintptr_t addr, size_t size, uintptr_t offset) const {180const ZErrno err = mremap(_base + offset, addr, size);181if (err) {182fatal("Failed to remap memory (%s)", err.to_string());183}184}185186void ZPhysicalMemoryBacking::unmap(uintptr_t addr, size_t size) const {187// Note that we must keep the address space reservation intact and just detach188// the backing memory. For this reason we map a new anonymous, non-accessible189// and non-reserved page over the mapping instead of actually unmapping.190const void* const res = mmap((void*)addr, size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);191if (res == MAP_FAILED) {192ZErrno err;193fatal("Failed to map memory (%s)", err.to_string());194}195}196197198