From 0c38f607836af40921ea2b58676b7c4a9fe33bef Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Fri, 2 Apr 2021 16:47:31 +0800 Subject: [PATCH 1/5] hw/arm/virt-acpi-build: Fix GSIV values of the {GERR, Sync} interrupts The GSIV values in SMMUv3 IORT node are not correct as they don't match the SMMUIrq enumeration, which describes the IRQ<->PIN mapping used by our emulated vSMMU. Fixes: a703b4f6c1ee ("hw/arm/virt-acpi-build: Add smmuv3 node in IORT table") Signed-off-by: Zenghui Yu Acked-by: Eric Auger Message-id: 20210402084731.93-1-yuzenghui@huawei.com Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index f5a2b2d4cb5..60fe2e65a76 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -292,8 +292,8 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) smmu->flags = cpu_to_le32(ACPI_IORT_SMMU_V3_COHACC_OVERRIDE); smmu->event_gsiv = cpu_to_le32(irq); smmu->pri_gsiv = cpu_to_le32(irq + 1); - smmu->gerr_gsiv = cpu_to_le32(irq + 2); - smmu->sync_gsiv = cpu_to_le32(irq + 3); + smmu->sync_gsiv = cpu_to_le32(irq + 2); + smmu->gerr_gsiv = cpu_to_le32(irq + 3); /* Identity RID mapping covering the whole input RID range */ idmap = &smmu->id_mapping_array[0]; From 017a913af4dff47ac5e62be613b9f8b88fc8fa96 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Fri, 2 Apr 2021 18:04:49 +0800 Subject: [PATCH 2/5] hw/arm/smmuv3: Emulate CFGI_STE_RANGE for an aligned range of StreamIDs In emulation of the CFGI_STE_RANGE command, we now take StreamID as the start of the invalidation range, regardless of whatever the Range is, whilst the spec clearly states that - "Invalidation is performed for an *aligned* range of 2^(Range+1) StreamIDs." - "The bottom Range+1 bits of the StreamID parameter are IGNORED, aligning the range to its size." Take CFGI_ALL (where Range == 31) as an example, if there are some random bits in the StreamID field, we'll fail to perform the full invalidation but get a strange range (e.g., SMMUSIDRange={.start=1, .end=0}) instead. Rework the emulation a bit to get rid of the discrepancy with the spec. Signed-off-by: Zenghui Yu Acked-by: Eric Auger Message-id: 20210402100449.528-1-yuzenghui@huawei.com Signed-off-by: Peter Maydell --- hw/arm/smmuv3.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 3b87324ce22..87056125357 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -980,16 +980,20 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) } case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */ { - uint32_t start = CMD_SID(&cmd); + uint32_t sid = CMD_SID(&cmd), mask; uint8_t range = CMD_STE_RANGE(&cmd); - uint64_t end = start + (1ULL << (range + 1)) - 1; - SMMUSIDRange sid_range = {start, end}; + SMMUSIDRange sid_range; if (CMD_SSEC(&cmd)) { cmd_error = SMMU_CERROR_ILL; break; } - trace_smmuv3_cmdq_cfgi_ste_range(start, end); + + mask = (1ULL << (range + 1)) - 1; + sid_range.start = sid & ~mask; + sid_range.end = sid_range.start + mask; + + trace_smmuv3_cmdq_cfgi_ste_range(sid_range.start, sid_range.end); g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste, &sid_range); break; From eb42297a59e103500bdd2c352c5b52f54b1c33cd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 6 Apr 2021 10:40:20 -0700 Subject: [PATCH 3/5] accel/tcg: Preserve PAGE_ANON when changing page permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using mprotect() to change PROT_* does not change the MAP_ANON previously set with mmap(). Our linux-user version of MTE only works with MAP_ANON pages, so losing PAGE_ANON caused MTE to stop working. Reported-by: Stephen Long Signed-off-by: Richard Henderson Reviewed-by: Alex Bennée Tested-by: Alex Bennée Signed-off-by: Peter Maydell --- accel/tcg/translate-all.c | 9 +++++-- tests/tcg/aarch64/Makefile.target | 2 +- tests/tcg/aarch64/mte-6.c | 43 +++++++++++++++++++++++++++++++ tests/tcg/aarch64/mte.h | 3 ++- 4 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 tests/tcg/aarch64/mte-6.c diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index f32df8b2404..ba6ab09790e 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2714,6 +2714,8 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) a missing call to h2g_valid. */ assert(end - 1 <= GUEST_ADDR_MAX); assert(start < end); + /* Only set PAGE_ANON with new mappings. */ + assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET)); assert_memory_lock(); start = start & TARGET_PAGE_MASK; @@ -2737,11 +2739,14 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) p->first_tb) { tb_invalidate_phys_page(addr, 0); } - if (reset_target_data && p->target_data) { + if (reset_target_data) { g_free(p->target_data); p->target_data = NULL; + p->flags = flags; + } else { + /* Using mprotect on a page does not change MAP_ANON. */ + p->flags = (p->flags & PAGE_ANON) | flags; } - p->flags = flags; } } diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index 56e48f4b34f..05b2622bfc9 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -37,7 +37,7 @@ AARCH64_TESTS += bti-2 # MTE Tests ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_MTE),) -AARCH64_TESTS += mte-1 mte-2 mte-3 mte-4 +AARCH64_TESTS += mte-1 mte-2 mte-3 mte-4 mte-6 mte-%: CFLAGS += -march=armv8.5-a+memtag endif diff --git a/tests/tcg/aarch64/mte-6.c b/tests/tcg/aarch64/mte-6.c new file mode 100644 index 00000000000..60d51d18be5 --- /dev/null +++ b/tests/tcg/aarch64/mte-6.c @@ -0,0 +1,43 @@ +#include "mte.h" + +void pass(int sig, siginfo_t *info, void *uc) +{ + assert(info->si_code == SEGV_MTESERR); + exit(0); +} + +int main(void) +{ + enable_mte(PR_MTE_TCF_SYNC); + + void *brk = sbrk(16); + if (brk == (void *)-1) { + perror("sbrk"); + return 2; + } + + if (mprotect(brk, 16, PROT_READ | PROT_WRITE | PROT_MTE)) { + perror("mprotect"); + return 2; + } + + int *p1, *p2; + long excl = 1; + + asm("irg %0,%1,%2" : "=r"(p1) : "r"(brk), "r"(excl)); + asm("gmi %0,%1,%0" : "+r"(excl) : "r"(p1)); + asm("irg %0,%1,%2" : "=r"(p2) : "r"(brk), "r"(excl)); + asm("stg %0,[%0]" : : "r"(p1)); + + *p1 = 0; + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = pass; + sa.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + + *p2 = 0; + + abort(); +} diff --git a/tests/tcg/aarch64/mte.h b/tests/tcg/aarch64/mte.h index 141cef522ce..0805676b116 100644 --- a/tests/tcg/aarch64/mte.h +++ b/tests/tcg/aarch64/mte.h @@ -48,7 +48,8 @@ static void enable_mte(int tcf) } } -static void *alloc_mte_mem(size_t size) +static void * alloc_mte_mem(size_t size) __attribute__((unused)); +static void * alloc_mte_mem(size_t size) { void *p = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); From ff38bca7d633868ac094ef86f3b246e8f57181d4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 6 Apr 2021 10:40:21 -0700 Subject: [PATCH 4/5] target/arm: Check PAGE_WRITE_ORG for MTE writeability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can remove PAGE_WRITE when (internally) marking a page read-only because it contains translated code. This can be triggered by tests/tcg/aarch64/bti-2, after having serviced SIGILL trampolines on the stack. Signed-off-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Peter Maydell --- target/arm/mte_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index 0bbb9ec3463..8be17e1b707 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -83,7 +83,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, uint8_t *tags; uintptr_t index; - if (!(flags & (ptr_access == MMU_DATA_STORE ? PAGE_WRITE : PAGE_READ))) { + if (!(flags & (ptr_access == MMU_DATA_STORE ? PAGE_WRITE_ORG : PAGE_READ))) { /* SIGSEGV */ arm_cpu_tlb_fill(env_cpu(env), ptr, ptr_size, ptr_access, ptr_mmu_idx, false, ra); From 52c01ada86611136e3122dd139788dbcbc292d86 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 6 Apr 2021 10:40:31 -0700 Subject: [PATCH 5/5] exec: Fix overlap of PAGE_ANON and PAGE_TARGET_1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unfortuately, the elements of PAGE_* were not in numerical order and so PAGE_ANON was added to an "unused" bit. As an arbitrary choice, move PAGE_TARGET_{1,2} together. Cc: Laurent Vivier Fixes: 26bab757d41b ("linux-user: Introduce PAGE_ANON") Buglink: https://bugs.launchpad.net/bugs/1922617 Signed-off-by: Richard Henderson Reviewed-by: Alex Bennée Reviewed-by: Laurent Vivier Tested-by: Laurent Vivier Tested-by: Nathan Chancellor Signed-off-by: Peter Maydell --- include/exec/cpu-all.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index d76b0b9e02d..32cfb634c6a 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -268,8 +268,8 @@ extern intptr_t qemu_host_page_mask; #define PAGE_RESERVED 0x0100 #endif /* Target-specific bits that will be used via page_get_flags(). */ -#define PAGE_TARGET_1 0x0080 -#define PAGE_TARGET_2 0x0200 +#define PAGE_TARGET_1 0x0200 +#define PAGE_TARGET_2 0x0400 #if defined(CONFIG_USER_ONLY) void page_dump(FILE *f);