From 50c750053672ce68e5b8208489cfea210e5f362d Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Tue, 13 Sep 2022 16:24:21 +0100 Subject: [PATCH] AAL: introduce capptr_size_round, use w/ metadata --- src/snmalloc/aal/aal.h | 5 +++++ src/snmalloc/aal/aal_cheri.h | 24 ++++++++++++++++++++++++ src/snmalloc/aal/aal_concept.h | 22 ++++++++++++++++++++++ src/snmalloc/backend/backend.h | 4 ++++ 4 files changed, 55 insertions(+) diff --git a/src/snmalloc/aal/aal.h b/src/snmalloc/aal/aal.h index 3ee0d91..3d44d56 100644 --- a/src/snmalloc/aal/aal.h +++ b/src/snmalloc/aal/aal.h @@ -215,6 +215,11 @@ namespace snmalloc return CapPtr::unsafe_from( a.template as_static().unsafe_ptr()); } + + static SNMALLOC_FAST_PATH size_t capptr_size_round(size_t sz) noexcept + { + return sz; + } }; } // namespace snmalloc diff --git a/src/snmalloc/aal/aal_cheri.h b/src/snmalloc/aal/aal_cheri.h index 25f35bb..7152e64 100644 --- a/src/snmalloc/aal/aal_cheri.h +++ b/src/snmalloc/aal/aal_cheri.h @@ -88,5 +88,29 @@ namespace snmalloc void* pb = __builtin_cheri_bounds_set_exact(a.unsafe_ptr(), size); return CapPtr::unsafe_from(static_cast(pb)); } + + static SNMALLOC_FAST_PATH size_t capptr_size_round(size_t sz) noexcept + { + /* + * Round up sz to the next representable value for the target + * architecture's choice of CHERI Concentrate T/B mantissa width. + * + * On Morello specifically, this intrinsic will (soon, as of this text + * being written) expand to a multi-instruction sequence to work around a + * bug in which sz values satisfying $\exists_E sz = ((1 << 12) - 1) << + * (E + 3)$ are incorrectly increased. If for some reason this ends up + * being at all hot, there will also be a + * __builtin_morello_round_representable_length_inexact, which will just + * return too big of a size for those values (by rounding up to $1 << (E + * + 15)$). While technically incorrect, this behavior is probably fine + * for snmalloc: we already slot metadata allocations into NAPOT holes + * and then return any unused space at the top, so the over-reach would, + * at the worst, just prevent said return, and our sizeclasses never run + * into this issue. That is, we're clear to use the __builtin_morello_* + * intrinsic if the multi-instruction sequence proves slow. See + * https://git.morello-project.org/morello/llvm-project/-/merge_requests/199 + */ + return __builtin_cheri_round_representable_length(sz); + } }; } // namespace snmalloc diff --git a/src/snmalloc/aal/aal_concept.h b/src/snmalloc/aal/aal_concept.h index 4fa0896..febd65b 100644 --- a/src/snmalloc/aal/aal_concept.h +++ b/src/snmalloc/aal/aal_concept.h @@ -59,6 +59,28 @@ namespace snmalloc AAL::template capptr_bound(auth, sz) } noexcept->ConceptSame>; + + /** + * Round up an allocation size to a size this architecture can represent. + * While there may also, in general, be alignment requirements for + * representability, in snmalloc so far we have not had reason to consider + * these explicitly: when we use our... + * + * - sizeclass machinery (for user-facing data), we assume that all + * sizeclasses describe architecturally representable aligned-and-sized + * regions + * + * - Range machinery (for internal meta-data), we always choose NAPOT + * regions big enough for the requested size (returning space above the + * allocation within such regions for use as smaller NAPOT regions). + * + * That is, capptr_size_round is not needed on the user-facing fast paths, + * merely internally for bootstrap and metadata management. + */ + { + AAL::capptr_size_round(sz) + } + noexcept->ConceptSame; }; template diff --git a/src/snmalloc/backend/backend.h b/src/snmalloc/backend/backend.h index 9401e71..12663be 100644 --- a/src/snmalloc/backend/backend.h +++ b/src/snmalloc/backend/backend.h @@ -43,6 +43,10 @@ namespace snmalloc alloc_meta_data(LocalState* local_state, size_t size) { capptr::Arena p; + + // Meta-data does not use our sizeclass machinery, so have Aal round up + size = Aal::capptr_size_round(size); + if (local_state != nullptr) { p = local_state->get_meta_range().alloc_range_with_leftover(size);