References:
tag_bit_set
will create a new tag block if the indexed block does not exist.
tag_bit_get
will return zero tags if the inidexed tag block does not exist.
This is how the tag (efficiently) stored: it exists only after the tag has been set/initialized. Otherwise, it is assumed to be always zero tags and will not have a tag block to store their values.
target/cheri-common/cheri_tagmem.c
/*
* Tagged Memory Emulation
*
* CHERI requires a 1-bit tag for every capability-aligned,
* capability-sized word in physical memory. This allows capabilities
* to be safely loaded and stored in meory without loss of integrity.
*
* For emulation purposes the tag is stored in a two-level array containing
* fixed size bitmaps. To reduce the amount of memory needed the tag flag array
* is allocated sparsely, 4K tags at at time, and on demand.
* This 4K number is arbitary and depending on the workload other sizes may be
* better.
*
* Note: We also support an mode where we use one byte per tag. This makes it
* easy to set or unset a tag without the need of locking or atomics.
* This requires eight times the memory. ==> Lele: use 7-bits for color.
*
* As tag accesses are not atomic with regard to data writes/reads spurious
* invalid capabilities could be created in a threaded context.
* Therefore, we don't use atomic bitwise RMW operations and the one byte per
* tag variant actually performs slightly worse due to increased memory usage.
*
* FIXME: find a solution to make tags safe (or just always disable multi-tcg)
*
* XXX Should consider adding a reference count per tag block so that
* blocks can be deallocated when no longer used maybe.
*
* FIXME: rewrite using somethign more like the upcoming MTE changes (https://github.com/rth7680/qemu/commits/tgt-arm-mte-user)
*/
Common functions
DEF_HELPER_4(store_cap_via_cap, void, env, i32, i32, tl)
->CHERI_HELPER_IMPL(store_cap_via_cap(CPUArchState *env, uint32_t cs, uint32_t cb, target_ulong offset))
-> store_cap_to_memory (target/cheri-common/op_helper_cheri_common.c)
-> cheri_tag_invalidate (see next list)
-> cheri_tag_set
-> tag_bit_get
-> tagblock_get_tag
-> tag_bit_set
-> cheri_tag_new_tagblk
-> tagblock_set_tag
void CHERI_HELPER_IMPL(cheri_invalidate_tags(CPUArchState *env,
target_ulong vaddr, MemOp op))
-> DEF_HELPER_3(cheri_invalidate_tags, void, env, cap_checked_ptr, memop)
-> CHERI_HELPER_IMPL(cheri_invalidate_tags(CPUArchState *env,
target_ulong vaddr, MemOp op))
-> cheri_tag_invalidate
-> cheri_tag_phys_invalidate
-> tagblock_get_tag
-> tagblock_clear_tag
cheri_tag_get_many(env, vaddr, reg, ret_paddr, pc)
-> tagblk = cheritag_get_block(vaddr,...): find the tag block, and the tag index in the block.
-> tagblock_get_tag(tagblk,tagidx[0-7]): read 8 tags one time, return as integer.
Target specific
MIPS:
CHERI_HELPER_IMPL(cscc_without_tcg(CPUArchState *env, uint32_t cs, uint32_t cb))
-> store_cap_to_memory (target/mips/op_helper_cheri.c)
target_ulong CHERI_HELPER_IMPL(cloadtags(CPUArchState *env, uint32_t cb, uint64_t cbcursor))
-> cheri_tag_get_many
RISCV:
void HELPER(amoswap_cap)(CPUArchState *env, uint32_t dest_reg,
uint32_t addr_reg, uint32_t val_reg)
-> store_cap_to_memory
static target_ulong sc_c_impl(CPUArchState *env, uint32_t addr_reg,
uint32_t val_reg, target_ulong offset,
uintptr_t _host_return_address)
-> store_cap_to_memory
cheri_tag_get_many
, CLoadTags, in target/cheri-common/cheri_tagmem.c.
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?