Skip to content

util: support and check tagged allocations in spad #4550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/extra/with-handholding.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ CPPFLAGS+=-DFD_FORKS_USE_HANDHOLDING=1
CPPFLAGS+=-DFD_GHOST_USE_HANDHOLDING=1
CPPFLAGS+=-DFD_SCRATCH_USE_HANDHOLDING=1
CPPFLAGS+=-DFD_SPAD_USE_HANDHOLDING=1
CPPFLAGS+=-DFD_SPAD_TAG_CHECK=1
CPPFLAGS+=-DFD_TOWER_USE_HANDHOLDING=1
CPPFLAGS+=-DFD_TMPL_USE_HANDHOLDING=1
CPPFLAGS+=-DFD_TXN_HANDHOLDING=1
Expand Down
4 changes: 2 additions & 2 deletions src/app/ledger/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ init_spads( fd_ledger_args_t * args, int has_tpool ) {
args->exec_spad_cnt = fd_tpool_worker_cnt( args->tpool );
for( ulong i=0UL; i<fd_tpool_worker_cnt( args->tpool ); i++ ) {
ulong total_mem_sz = args->thread_mem_bound;
uchar * mem = fd_wksp_alloc_laddr( args->wksp, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( total_mem_sz ), 999UL );
uchar * mem = fd_wksp_alloc_laddr( args->wksp, fd_spad_align(), fd_spad_footprint( total_mem_sz ), 999UL );
fd_spad_t * spad = fd_spad_join( fd_spad_new( mem, total_mem_sz ) );
if( FD_UNLIKELY( !spad ) ) {
FD_LOG_ERR(( "failed to allocate spad" ));
Expand All @@ -162,7 +162,7 @@ init_spads( fd_ledger_args_t * args, int has_tpool ) {
that exist at the slot_ctx/epoch_ctx. It should encapsulate all allocations
that happen outside of transaction execution. */

uchar * mem = fd_wksp_alloc_laddr( args->wksp, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( args->runtime_mem_bound ), 999UL );
uchar * mem = fd_wksp_alloc_laddr( args->wksp, fd_spad_align(), fd_spad_footprint( args->runtime_mem_bound ), 999UL );
fd_spad_t * spad = fd_spad_join( fd_spad_new( mem, args->runtime_mem_bound ) );
if( FD_UNLIKELY( !spad ) ) {
FD_LOG_ERR(( "Failed to allocate runtime spad" ));
Expand Down
4 changes: 2 additions & 2 deletions src/flamenco/runtime/tests/fd_exec_instr_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,7 @@ _block_context_create_and_exec( fd_exec_instr_test_runner_t * runner,
ulong exec_spads_cnt = 2UL;
ulong exec_spad_mem_max = 1UL << 30;
for( ulong i=0UL; i<worker_max; i++ ) {
void * exec_spad_mem = fd_spad_alloc( runtime_spad, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( exec_spad_mem_max ) );
void * exec_spad_mem = fd_spad_alloc( runtime_spad, fd_spad_align(), fd_spad_footprint( exec_spad_mem_max ) );
fd_spad_t * exec_spad = fd_spad_join( fd_spad_new( exec_spad_mem, exec_spad_mem_max ) );
exec_spads[i] = exec_spad;
}
Expand Down Expand Up @@ -1987,7 +1987,7 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner,

/* Need to setup txn_descriptor for txn account write checks (see fd_txn_account_is_writable_idx)
FIXME: this could probably go in fd_exec_test_instr_context_create? */
fd_txn_t * txn_descriptor = (fd_txn_t *)fd_spad_alloc_debug( spad, fd_txn_align(), fd_txn_footprint( ctx->txn_ctx->instr_info_cnt, 0UL ) );
fd_txn_t * txn_descriptor = (fd_txn_t *)fd_spad_alloc_debug( spad, fd_txn_align(), fd_txn_footprint( ctx->txn_ctx->instr_info_cnt, 0UL ), 0UL );
txn_descriptor->transaction_version = FD_TXN_V0;
txn_descriptor->acct_addr_cnt = (ushort)ctx->txn_ctx->accounts_cnt;

Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/runtime/tests/fd_exec_sol_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ sol_compat_wksp_init( ulong wksp_page_sz ) {
}
FD_TEST( wksp );

spad_mem = fd_wksp_alloc_laddr( wksp, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ ), WKSP_INIT_ALLOC_TAG ); /* 4738713960 B */
spad_mem = fd_wksp_alloc_laddr( wksp, fd_spad_align(), fd_spad_footprint( FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ ), WKSP_INIT_ALLOC_TAG ); /* 4738713960 B */
FD_TEST( spad_mem );

features.struct_size = sizeof(sol_compat_features_t);
Expand Down
4 changes: 2 additions & 2 deletions src/flamenco/runtime/tests/fd_vm_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ do{
break;
}
ulong rodata_sz = input->vm_ctx.rodata->size;
uchar * rodata = fd_spad_alloc_debug( spad, 8UL, rodata_sz );
uchar * rodata = fd_spad_alloc_debug( spad, 8UL, rodata_sz, 0UL );
memcpy( rodata, input->vm_ctx.rodata->bytes, rodata_sz );

/* Enable direct_mapping for SBPF version >= v1 */
Expand Down Expand Up @@ -338,7 +338,7 @@ fd_setup_vm_input_regions( fd_vm_input_region_t * input,
continue; /* skip empty regions https://github.com/anza-xyz/agave/blob/3072c1a72b2edbfa470ca869f1ea891dfb6517f2/programs/bpf_loader/src/serialization.rs#L136 */
}

uchar * haddr = fd_spad_alloc_debug( spad, 8UL, array->size );
uchar * haddr = fd_spad_alloc_debug( spad, 8UL, array->size, 0UL );
fd_memcpy( haddr, array->bytes, array->size );
input[input_idx].vaddr_offset = offset;
input[input_idx].haddr = (ulong)haddr;
Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/snapshot/fd_snapshot_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ cmd_dump( int argc,
/* With spad */

ulong mem_max = args->zstd_window_sz + (1<<29); /* manifest plus 512 MiB headroom */
uchar * mem = fd_wksp_alloc_laddr( wksp, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( mem_max ), 1UL );
uchar * mem = fd_wksp_alloc_laddr( wksp, fd_spad_align(), fd_spad_footprint( mem_max ), 1UL );
fd_spad_t * spad = fd_spad_join( fd_spad_new( mem, mem_max ) );
if( FD_UNLIKELY( !spad ) ) {
FD_LOG_ERR(( "Failed to allocate spad" ));
Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/snapshot/test_snapshot_restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ main( int argc,

void * restore_mem = fd_wksp_alloc_laddr( wksp, fd_snapshot_restore_align(), fd_snapshot_restore_footprint(), static_tag );

fd_spad_t * _spad = fd_spad_new( fd_wksp_alloc_laddr( wksp, FD_SPAD_ALIGN, FD_SPAD_FOOTPRINT( 4194304UL ), static_tag ), 4194304UL );
fd_spad_t * _spad = fd_spad_new( fd_wksp_alloc_laddr( wksp, fd_spad_align(), fd_spad_footprint( 4194304UL ), static_tag ), 4194304UL );
fd_spad_push( _spad );
FD_LOG_WARNING(("SPAD %lu", _spad->mem_max));

Expand Down
63 changes: 51 additions & 12 deletions src/util/spad/fd_spad.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,39 @@ fd_spad_pop_debug( fd_spad_t * spad ) {
SELECT_DEBUG_IMPL(fd_spad_pop)( spad );
}

#if FD_SPAD_TAG_CHECK
static void
fd_spad_check_tag( fd_spad_t * spad,
ulong tag ) {

ulong * tag_mem_used = (ulong *)(spad+1UL);
if( FD_UNLIKELY( tag_mem_used[ spad->frame_free * spad->tag_max + tag ] >
tag_mem_used[ FD_SPAD_FRAME_MAX * spad->tag_max + tag ] ) ) {
FD_LOG_CRIT(( "tag %lu overflow %lu > %lu",
tag,
tag_mem_used[ spad->frame_free * spad->tag_max + tag ],
tag_mem_used[ FD_SPAD_FRAME_MAX * spad->tag_max + tag ] ));
}

}
#endif

void *
fd_spad_alloc_debug( fd_spad_t * spad,
ulong align,
ulong sz ) {
ulong sz,
ulong tag ) {
if( FD_UNLIKELY( !fd_spad_frame_used( spad ) ) ) FD_LOG_CRIT(( "not in a frame" ));
if( FD_UNLIKELY( (!!align) & (!fd_ulong_is_pow2( align ) ) ) ) FD_LOG_CRIT(( "bad align" ));
if( FD_UNLIKELY( fd_spad_alloc_max( spad, align )<sz ) ) FD_LOG_CRIT(( "bad sz" ));
return SELECT_DEBUG_IMPL(fd_spad_alloc)( spad, align, sz );
if( FD_UNLIKELY( (!!align) & (!fd_ulong_is_pow2( align ) ) ) ) FD_LOG_CRIT(( "bad align %lu", align ));
if( FD_UNLIKELY( fd_spad_alloc_max( spad, align )<sz ) ) FD_LOG_CRIT(( "bad sz %lu align %lu max %lu alloc_max %lu", sz, align, fd_spad_mem_max( spad ), fd_spad_alloc_max( spad, align ) ));
#if FD_SPAD_TAG_CHECK
if( FD_UNLIKELY( fd_spad_tag_max( spad )<=tag ) ) FD_LOG_CRIT(( "bad tag %lu tag_max %lu", tag, fd_spad_tag_max( spad ) ));
#endif
void * rv = SELECT_DEBUG_IMPL(fd_spad_alloc)( spad, align, sz, tag );
#if FD_SPAD_TAG_CHECK
fd_spad_check_tag( spad, tag );
#endif
return rv;
}

void
Expand All @@ -103,11 +128,19 @@ fd_spad_trim_debug( fd_spad_t * spad,
void *
fd_spad_prepare_debug( fd_spad_t * spad,
ulong align,
ulong max ) {
ulong max,
ulong tag ) {
if( FD_UNLIKELY( !fd_spad_frame_used( spad ) ) ) FD_LOG_CRIT(( "not in a frame" ));
if( FD_UNLIKELY( (!!align) & (!fd_ulong_is_pow2( align ) ) ) ) FD_LOG_CRIT(( "bad align" ));
if( FD_UNLIKELY( fd_spad_alloc_max( spad, align )<max ) ) FD_LOG_CRIT(( "bad max of %lu", max ));
return SELECT_DEBUG_IMPL(fd_spad_prepare)( spad, align, max );
if( FD_UNLIKELY( (!!align) & (!fd_ulong_is_pow2( align ) ) ) ) FD_LOG_CRIT(( "bad align %lu", align ));
if( FD_UNLIKELY( fd_spad_alloc_max( spad, align )<max ) ) FD_LOG_CRIT(( "bad max %lu align %lu max %lu alloc_max %lu", max, align, fd_spad_mem_max( spad ), fd_spad_alloc_max( spad, align ) ));
#if FD_SPAD_TAG_CHECK
if( FD_UNLIKELY( fd_spad_tag_max( spad )<=tag ) ) FD_LOG_CRIT(( "bad tag %lu tag_max %lu", tag, fd_spad_tag_max( spad ) ));
#endif
void * rv = SELECT_DEBUG_IMPL(fd_spad_prepare)( spad, align, max, tag );
#if FD_SPAD_TAG_CHECK
fd_spad_check_tag( spad, tag );
#endif
return rv;
}

void
Expand All @@ -126,6 +159,10 @@ fd_spad_publish_debug( fd_spad_t * spad,
/* FIXME: check if in prepare? needs extra state and a lot of extra
tracking that state */
SELECT_DEBUG_IMPL(fd_spad_publish)( spad, sz );

#if FD_SPAD_TAG_CHECK
fd_spad_check_tag( spad, spad->inprep_tag );
#endif
}

#undef SELECT_DEBUG_IMPL
Expand Down Expand Up @@ -199,15 +236,16 @@ fd_spad_pop_sanitizer_impl( fd_spad_t * spad ) {
void *
fd_spad_alloc_sanitizer_impl( fd_spad_t * spad,
ulong align,
ulong sz ) {
ulong sz,
ulong tag ) {
/* enforce a minimum alignment of FD_ASAN_ALIGN or FD_MSAN_ALIGN when running ASAN or MSAN respectively */
#if FD_HAS_DEEPASAN
align = fd_ulong_if( align>0UL, fd_ulong_max( align, FD_ASAN_ALIGN ), FD_SPAD_ALLOC_ALIGN_DEFAULT ); /* typically compile time */
#elif FD_HAS_MSAN
align = fd_ulong_if( align>0UL, fd_ulong_max( align, FD_MSAN_ALIGN ), FD_SPAD_ALLOC_ALIGN_DEFAULT ); /* typically compile time */
#endif

void * buf = fd_spad_alloc_impl( spad, align, sz );
void * buf = fd_spad_alloc_impl( spad, align, sz, tag );

/* first poison from buf to mem_max to cancel any in-progress prepare.
buf is guaranteed to be an 8-byte aligned adddress */
Expand Down Expand Up @@ -253,15 +291,16 @@ fd_spad_trim_sanitizer_impl( fd_spad_t * spad,
void *
fd_spad_prepare_sanitizer_impl( fd_spad_t * spad,
ulong align,
ulong max ) {
ulong max,
ulong tag ) {
/* enforce a minimum alignment of FD_ASAN_ALIGN or FD_MSAN_ALIGN when running ASAN or MSAN respectively */
#if FD_HAS_DEEPASAN
align = fd_ulong_if( align>0UL, fd_ulong_max( align, FD_ASAN_ALIGN ), FD_SPAD_ALLOC_ALIGN_DEFAULT ); /* typically compile time */
#elif FD_HAS_MSAN
align = fd_ulong_if( align>0UL, fd_ulong_max( align, FD_MSAN_ALIGN ), FD_SPAD_ALLOC_ALIGN_DEFAULT ); /* typically compile time */
#endif

void * buf = fd_spad_prepare_impl( spad, align, max );
void * buf = fd_spad_prepare_impl( spad, align, max, tag );

/* unpoison memory starting at buf, which is guaranteed to be 8 byte aligned */
fd_asan_unpoison( buf, spad->mem_max - spad->mem_used );
Expand Down
Loading
Loading