mbox series

[0/6] kselftest: arm64/mte: Tests for user-space MTE

Message ID 20200901092719.9918-1-amit.kachhap@arm.com
Headers show
Series kselftest: arm64/mte: Tests for user-space MTE | expand

Message

Amit Kachhap Sept. 1, 2020, 9:27 a.m. UTC
These patch series adds below kselftests to test the user-space support for the
ARMv8.5 Memory Tagging Extension present in arm64 tree [1].

1) This test-case verifies that the memory allocated by kernel mmap interface
can support tagged memory access. It first checks the presence of tags at
address[56:59] and then proceeds with read and write. The pass criteria for
this test is that tag fault exception should not happen.

2) This test-case crosses the valid memory to the invalid memory. In this
memory area valid tags are not inserted so read and write should not pass. The
pass criteria for this test is that tag fault exception should happen for all
the illegal addresses. This test also verfies that PSTATE.TCO works properly.

3) This test-case verifies that the memory inherited by child process from
parent process should have same tags copied. The pass criteria for this test is
that tag fault exception should not happen.

4) This test checks different mmap flags with PROT_MTE memory protection.

5) This testcase checks that KSM should not merge pages containing different
MTE tag values. However, if the tags are same then the pages may merge. This
testcase uses the generic ksm sysfs interfaces to verify the MTE behaviour, so
this testcase is not fullproof and may be impacted due to other load in the system.

6) Fifth test verifies that syscalls read/write etc works by considering that
user pointer has valid/invalid allocation tags.

To simplify the testing, a copy of the patchset on top of a recent linux
tree can be found at [2].


Thanks,
Amit Daniel

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/mte
[2]: http://linux-arm.org/git?p=linux-ak.git;a=shortlog;h=refs/heads/kselftest-mte-mainline-v1


Amit Daniel Kachhap (6):
  kselftest/arm64: Add utilities and a test to validate mte memory
  kselftest/arm64: Verify mte tag inclusion via prctl
  kselftest/arm64: Check forked child mte memory accessibility
  kselftest/arm64: Verify all different mmap MTE options
  kselftest/arm64: Verify KSM page merge for MTE pages
  kselftest/arm64: Check mte tagged user address in kernel

 tools/testing/selftests/arm64/Makefile        |   2 +-
 tools/testing/selftests/arm64/mte/.gitignore  |   6 +
 tools/testing/selftests/arm64/mte/Makefile    |  29 ++
 .../selftests/arm64/mte/check_buffer_fill.c   | 476 ++++++++++++++++++
 .../selftests/arm64/mte/check_child_memory.c  | 195 +++++++
 .../selftests/arm64/mte/check_ksm_options.c   | 131 +++++
 .../selftests/arm64/mte/check_mmap_options.c  | 262 ++++++++++
 .../arm64/mte/check_tags_inclusion.c          | 183 +++++++
 .../selftests/arm64/mte/check_user_mem.c      | 118 +++++
 .../selftests/arm64/mte/mte_common_util.c     | 374 ++++++++++++++
 .../selftests/arm64/mte/mte_common_util.h     | 135 +++++
 tools/testing/selftests/arm64/mte/mte_def.h   |  26 +
 .../testing/selftests/arm64/mte/mte_helper.S  | 116 +++++
 13 files changed, 2052 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/arm64/mte/.gitignore
 create mode 100644 tools/testing/selftests/arm64/mte/Makefile
 create mode 100644 tools/testing/selftests/arm64/mte/check_buffer_fill.c
 create mode 100644 tools/testing/selftests/arm64/mte/check_child_memory.c
 create mode 100644 tools/testing/selftests/arm64/mte/check_ksm_options.c
 create mode 100644 tools/testing/selftests/arm64/mte/check_mmap_options.c
 create mode 100644 tools/testing/selftests/arm64/mte/check_tags_inclusion.c
 create mode 100644 tools/testing/selftests/arm64/mte/check_user_mem.c
 create mode 100644 tools/testing/selftests/arm64/mte/mte_common_util.c
 create mode 100644 tools/testing/selftests/arm64/mte/mte_common_util.h
 create mode 100644 tools/testing/selftests/arm64/mte/mte_def.h
 create mode 100644 tools/testing/selftests/arm64/mte/mte_helper.S

Comments

Catalin Marinas Sept. 21, 2020, 11:36 a.m. UTC | #1
On Tue, Sep 01, 2020 at 02:57:14PM +0530, Amit Daniel Kachhap wrote:
> diff --git a/tools/testing/selftests/arm64/mte/mte_common_util.c b/tools/testing/selftests/arm64/mte/mte_common_util.c
> new file mode 100644
> index 000000000000..ac311919567d
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/mte/mte_common_util.c
> @@ -0,0 +1,374 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2020 ARM Limited
> +
> +#include <fcntl.h>
> +#include <sched.h>
> +#include <signal.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +#include <linux/auxvec.h>
> +#include <sys/auxv.h>
> +#include <sys/mman.h>
> +#include <sys/prctl.h>
> +
> +#include <asm/hwcap.h>
> +
> +#include "kselftest.h"
> +#include "mte_common_util.h"
> +#include "mte_def.h"
> +
> +/* The temp file must be created in a tmpfs filesystem */
> +#ifdef ANDROID
> +# define TEMPFILENAME    "/storage/tmp_XXXXXX"
> +#else
> +# define TEMPFILENAME    "/tmp/tmp_XXXXXX"
> +#endif

That's not guaranteed to be tmpfs (it's not on my Debian install). I
think you'd have a better chance with /dev/shm/tmp_XXXXXX.
Catalin Marinas Sept. 21, 2020, 2:18 p.m. UTC | #2
On Tue, Sep 01, 2020 at 02:57:14PM +0530, Amit Daniel Kachhap wrote:
> diff --git a/tools/testing/selftests/arm64/mte/mte_helper.S b/tools/testing/selftests/arm64/mte/mte_helper.S

> new file mode 100644

> index 000000000000..91af6d1293f8

> --- /dev/null

> +++ b/tools/testing/selftests/arm64/mte/mte_helper.S

> @@ -0,0 +1,116 @@

> +/* SPDX-License-Identifier: GPL-2.0 */

> +/* Copyright (C) 2020 ARM Limited */

> +

> +#include "mte_def.h"

> +

> +#define ENTRY(name) \

> +	.globl name ;\

> +	.p2align 2;\

> +	.type name, @function ;\

> +name:

> +

> +#define ENDPROC(name) \

> +	.size name, .-name ;

> +

> +	.text

> +/*

> + * mte_insert_random_tag: Insert random tag and different from

> + *			 the orginal tag if source pointer has it.

> + * Input:

> + *		x0 - source pointer with a tag/no-tag

> + * Return:

> + *		x0 - pointer with random tag

> + */

> +ENTRY(mte_insert_random_tag)

> +	mov	x1, #0x0

> +	gmi	x1, x0, x1

> +	irg	x0, x0, x1

> +	ret

> +ENDPROC(mte_insert_random_tag)


What was the reason for gmi here? The test fails when you have an
include mask of 0x8000 (exclude mask 0x7fff) and x0 has tag 0xf. In this
case we exclude the only allowed tag here, so the CPU falls back to the
default tag 0.

You can (a) stop the check_multiple_included_tags() earlier to have two
allowed tags here, (b) clear the pointer old tag so that you don't end
up in this scenario or (c) simply remove the gmi. My preference is the
latter, we don't test the hardware here, we only want to check whether
the kernel sets the GCR_EL1 correctly.

BTW, you also remove mov x1, #0, just:

	irg	x0, x0, xzr

-- 
Catalin
Catalin Marinas Sept. 21, 2020, 4:43 p.m. UTC | #3
On Mon, Sep 21, 2020 at 03:18:19PM +0100, Catalin Marinas wrote:
> On Tue, Sep 01, 2020 at 02:57:14PM +0530, Amit Daniel Kachhap wrote:

> > diff --git a/tools/testing/selftests/arm64/mte/mte_helper.S b/tools/testing/selftests/arm64/mte/mte_helper.S

> > new file mode 100644

> > index 000000000000..91af6d1293f8

> > --- /dev/null

> > +++ b/tools/testing/selftests/arm64/mte/mte_helper.S

> > @@ -0,0 +1,116 @@

> > +/* SPDX-License-Identifier: GPL-2.0 */

> > +/* Copyright (C) 2020 ARM Limited */

> > +

> > +#include "mte_def.h"

> > +

> > +#define ENTRY(name) \

> > +	.globl name ;\

> > +	.p2align 2;\

> > +	.type name, @function ;\

> > +name:

> > +

> > +#define ENDPROC(name) \

> > +	.size name, .-name ;

> > +

> > +	.text

> > +/*

> > + * mte_insert_random_tag: Insert random tag and different from

> > + *			 the orginal tag if source pointer has it.

> > + * Input:

> > + *		x0 - source pointer with a tag/no-tag

> > + * Return:

> > + *		x0 - pointer with random tag

> > + */

> > +ENTRY(mte_insert_random_tag)

> > +	mov	x1, #0x0

> > +	gmi	x1, x0, x1

> > +	irg	x0, x0, x1

> > +	ret

> > +ENDPROC(mte_insert_random_tag)

> 

> What was the reason for gmi here? The test fails when you have an

> include mask of 0x8000 (exclude mask 0x7fff) and x0 has tag 0xf. In this

> case we exclude the only allowed tag here, so the CPU falls back to the

> default tag 0.

> 

> You can (a) stop the check_multiple_included_tags() earlier to have two

> allowed tags here, (b) clear the pointer old tag so that you don't end

> up in this scenario or (c) simply remove the gmi. My preference is the

> latter, we don't test the hardware here, we only want to check whether

> the kernel sets the GCR_EL1 correctly.

> 

> BTW, you also remove mov x1, #0, just:

> 

> 	irg	x0, x0, xzr


Ah, removing gmi breaks the check_user_mem test as it occasionally gets
the same tag when it expects to be different. I'll leave this to you to
fix, maybe use two different functions, one with gmi and another
without.

In addition, could you please add the PR_MTE_* definitions and PROT_MTE
to a header file in the MTE kselftests (mte-def.h maybe)? They should be
bracketed with #ifndef ... #endif. The reason is that we'd like to queue
these patches on their own branch on top of vanilla 5.9-rc3 rather than
on top of for-next/mte.

Thanks.

-- 
Catalin