Control this with x-tagged-pages, which is off by default. The limitation to non-shared pages is not part of a future kernel API, but a limitation of linux-user not being able to map virtual pages back to physical pages.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- v2: Add the x-tagged-pages cpu property --- target/arm/cpu.h | 4 ++++ target/arm/cpu64.c | 20 ++++++++++++++++++++ target/arm/mte_helper.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index c3609ef9d5..272df43d3c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -912,6 +912,10 @@ struct ARMCPU { */ bool cfgend; +#ifdef CONFIG_USER_ONLY + bool tagged_pages; +#endif + QLIST_HEAD(, ARMELChangeHook) pre_el_change_hooks; QLIST_HEAD(, ARMELChangeHook) el_change_hooks; diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index ac1e2dc2c4..4bf498f778 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -279,6 +279,20 @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name, error_propagate(errp, err); } +#ifdef CONFIG_USER_ONLY +static bool aarch64_cpu_get_tagged_pages(Object *obj, Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + return cpu->tagged_pages; +} + +static void aarch64_cpu_set_tagged_pages(Object *obj, bool val, Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + cpu->tagged_pages = val; +} +#endif + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); * otherwise, a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; @@ -389,6 +403,12 @@ static void aarch64_max_initfn(Object *obj) */ cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ cpu->dcz_blocksize = 7; /* 512 bytes */ + + object_property_add_bool(obj, "x-tagged-pages", + aarch64_cpu_get_tagged_pages, + aarch64_cpu_set_tagged_pages, NULL); + object_property_set_description(obj, "x-tagged-pages", + "Set on/off MemAttr Tagged for all pages", NULL); #endif cpu->sve_max_vq = ARM_MAX_VQ; diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index 657383ba0e..797c6229ab 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -29,8 +29,39 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, uint64_t ptr, bool write, uintptr_t ra) { #ifdef CONFIG_USER_ONLY - /* Tag storage not implemented. */ - return NULL; + ARMCPU *cpu = env_archcpu(env); + uint8_t *tags; + uintptr_t index; + int flags; + + flags = page_get_flags(ptr); + + if (!(flags & PAGE_VALID) || !(flags & (write ? PAGE_WRITE : PAGE_READ))) { + /* SIGSEGV */ + env->exception.vaddress = ptr; + cpu_restore_state(CPU(cpu), ra, true); + raise_exception(env, EXCP_DATA_ABORT, 0, 1); + } + + if (!cpu->tagged_pages) { + /* Tag storage is disabled. */ + return NULL; + } + if (flags & PAGE_SHARED) { + /* There may be multiple mappings; pretend not implemented. */ + return NULL; + } + + tags = page_get_target_data(ptr); + if (tags == NULL) { + size_t alloc_size = TARGET_PAGE_SIZE >> (LOG2_TAG_GRANULE + 1); + tags = page_alloc_target_data(ptr, alloc_size); + assert(tags != NULL); + } + + index = extract32(ptr, LOG2_TAG_GRANULE + 1, + TARGET_PAGE_BITS - LOG2_TAG_GRANULE - 1); + return tags + index; #else CPUState *cs = env_cpu(env); uintptr_t index; -- 2.17.1