selftests/x86/lam: Add test cases for LAM vs thread creation

LAM enabling is only allowed when the process has single thread.
LAM mode is inherited into child thread.

Trying to enable LAM after spawning a thread has to fail.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/20230312112612.31869-18-kirill.shutemov%40linux.intel.com
This commit is contained in:
Kirill A. Shutemov 2023-03-12 14:26:12 +03:00 committed by Dave Hansen
parent 34821473de
commit dfd7a1569e

View file

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -12,6 +13,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sched.h>
#include <sys/uio.h>
#include <linux/io_uring.h>
@ -50,6 +52,8 @@
#define PAGE_SIZE (4 << 10)
#define STACK_SIZE 65536
#define barrier() ({ \
__asm__ __volatile__("" : : : "memory"); \
})
@ -731,6 +735,75 @@ static int handle_inheritance(struct testcases *test)
return 0;
}
static int thread_fn_get_lam(void *arg)
{
return get_lam();
}
static int thread_fn_set_lam(void *arg)
{
struct testcases *test = arg;
return set_lam(test->lam);
}
static int handle_thread(struct testcases *test)
{
char stack[STACK_SIZE];
int ret, child_ret;
int lam = 0;
pid_t pid;
/* Set LAM mode in parent process */
if (!test->later) {
lam = test->lam;
if (set_lam(lam) != 0)
return 1;
}
pid = clone(thread_fn_get_lam, stack + STACK_SIZE,
SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_VM, NULL);
if (pid < 0) {
perror("Clone failed.");
return 1;
}
waitpid(pid, &child_ret, 0);
ret = WEXITSTATUS(child_ret);
if (lam != ret)
return 1;
if (test->later) {
if (set_lam(test->lam) != 0)
return 1;
}
return 0;
}
static int handle_thread_enable(struct testcases *test)
{
char stack[STACK_SIZE];
int ret, child_ret;
int lam = test->lam;
pid_t pid;
pid = clone(thread_fn_set_lam, stack + STACK_SIZE,
SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_VM, test);
if (pid < 0) {
perror("Clone failed.");
return 1;
}
waitpid(pid, &child_ret, 0);
ret = WEXITSTATUS(child_ret);
if (lam != ret)
return 1;
return 0;
}
static void run_test(struct testcases *test, int count)
{
int i, ret = 0;
@ -846,6 +919,25 @@ static struct testcases inheritance_cases[] = {
.test_func = handle_inheritance,
.msg = "FORK: LAM_U57, child process should get LAM mode same as parent\n",
},
{
.expected = 0,
.lam = LAM_U57_BITS,
.test_func = handle_thread,
.msg = "THREAD: LAM_U57, child thread should get LAM mode same as parent\n",
},
{
.expected = 1,
.lam = LAM_U57_BITS,
.test_func = handle_thread_enable,
.msg = "THREAD: [NEGATIVE] Enable LAM in child.\n",
},
{
.expected = 1,
.later = 1,
.lam = LAM_U57_BITS,
.test_func = handle_thread,
.msg = "THREAD: [NEGATIVE] Enable LAM in parent after thread created.\n",
},
{
.expected = 0,
.lam = LAM_U57_BITS,