Tag Mem

References:

  • github/qemu, 202005.

tagbit{set|get}

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.

Overview

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.
    • Currently only called in MIPS.

More

Created May 25, 2020 // Last Updated Aug 13, 2020

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?