From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>,
Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Cc: devel@openvz.org
Subject: [Devel] [PATCH hci-8.1 v4 3/5] selftests/ve: check CPUID override right after entering a VE
Date: Wed, 07 Oct 2026 00:12:53 +0200 [thread overview]
Message-ID: <20261007-b4-prep-khorenko-vstor-148656-cpuid-v4-3-bf16c29bea24@virtuozzo.com> (raw)
In-Reply-To: <20261007-b4-prep-khorenko-vstor-148656-cpuid-v4-0-bf16c29bea24@virtuozzo.com>
Add a case where the child executes CPUID straight after unshare(),
without stopping or blocking in between, and expects the table values.
Before the kernel change the override took effect only after the first
context switch, so the child saw the hardware values.
A tick can still preempt the child in that window, so the case runs
the sequence several times: a kernel that arms faulting only at the
switch has to get lucky every time.
https://virtuozzo.atlassian.net/browse/VSTOR-148843
Feature: x86: cpu pools (cpuid override)
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
.../testing/selftests/ve/ve_cpuid_override_test.c | 62 ++++++++++++++++------
1 file changed, 45 insertions(+), 17 deletions(-)
diff --git a/tools/testing/selftests/ve/ve_cpuid_override_test.c b/tools/testing/selftests/ve/ve_cpuid_override_test.c
index f2883539bac3f..d940acc7ee792 100644
--- a/tools/testing/selftests/ve/ve_cpuid_override_test.c
+++ b/tools/testing/selftests/ve/ve_cpuid_override_test.c
@@ -31,6 +31,7 @@
#define CPUID_OVERRIDE_PATH "/proc/vz/cpuid_override"
#define CPUID_LEAF 1
#define CPUID_LINE_LEN 128
+#define NO_RESCHED_ROUNDS 20
/* The kernel takes a table back only in one write below a page. */
#define CPUID_WRITE_MAX 4096
#define CPUID_SAVED_MAX (CPUID_WRITE_MAX + 1)
@@ -49,14 +50,15 @@ static void do_cpuid(unsigned int leaf, struct cpuid_regs *r)
struct child_ctx {
int result_pipe[2];
+ int stop;
};
/*
* The child enters a fresh VE, so it is armed with the table state of that
- * moment, then reports its view of the leaf to the parent over a pipe. It
- * stops itself in between: a stopped task is off the CPU, so the resume is
- * a context switch, and the parent may change the table while the child
- * stands still.
+ * moment, then reports its view of the leaf to the parent over a pipe. With
+ * @stop it stops itself in between: a stopped task is off the CPU, so the
+ * resume is a context switch, and the parent may change the table while
+ * the child stands still.
*/
static int cpuid_child(struct child_ctx *ctx)
{
@@ -66,7 +68,7 @@ static int cpuid_child(struct child_ctx *ctx)
if (unshare(CLONE_NEWVE) < 0)
return 21;
- if (raise(SIGSTOP))
+ if (ctx->stop && raise(SIGSTOP))
return 22;
do_cpuid(CPUID_LEAF, &r);
@@ -148,7 +150,7 @@ FIXTURE_TEARDOWN_PARENT(ve_cpuid_override)
close(cgv2_fd);
}
-/* Fork the child into the VE and return once it stands still there. */
+/* Fork the child into the VE; with @stop return once it stands still. */
static pid_t spawn_cpuid_child(struct __test_metadata *_metadata,
FIXTURE_DATA(ve_cpuid_override) * self,
struct child_ctx *ctx)
@@ -170,16 +172,20 @@ static pid_t spawn_cpuid_child(struct __test_metadata *_metadata,
ASSERT_GE(pid, 0);
close(ctx->result_pipe[1]);
- ASSERT_GE(waitpid(pid, &status, WUNTRACED), 0);
- if (!WIFSTOPPED(status)) {
- /* Reaped: the pid may be reused, keep it from teardown. */
- self->child = 0;
- if (WIFEXITED(status))
- TH_LOG("child exited with %d", WEXITSTATUS(status));
- if (WIFSIGNALED(status))
- TH_LOG("child killed by signal %d", WTERMSIG(status));
+ if (ctx->stop) {
+ ASSERT_GE(waitpid(pid, &status, WUNTRACED), 0);
+ if (!WIFSTOPPED(status)) {
+ /* Reaped: the pid may be reused, keep it from teardown. */
+ self->child = 0;
+ if (WIFEXITED(status))
+ TH_LOG("child exited with %d",
+ WEXITSTATUS(status));
+ if (WIFSIGNALED(status))
+ TH_LOG("child killed by signal %d",
+ WTERMSIG(status));
+ }
+ ASSERT_TRUE(WIFSTOPPED(status));
}
- ASSERT_TRUE(WIFSTOPPED(status));
return pid;
}
@@ -208,7 +214,7 @@ static void collect_cpuid_child(struct __test_metadata *_metadata,
TEST_F(ve_cpuid_override, ve_sees_table_host_sees_hardware)
{
- struct child_ctx ctx;
+ struct child_ctx ctx = { .stop = 1 };
struct cpuid_regs r;
pid_t pid;
@@ -229,7 +235,7 @@ TEST_F(ve_cpuid_override, ve_sees_table_host_sees_hardware)
TEST_F(ve_cpuid_override, flushed_table_falls_back_to_hardware)
{
- struct child_ctx ctx;
+ struct child_ctx ctx = { .stop = 1 };
struct cpuid_regs r;
pid_t pid;
@@ -244,4 +250,26 @@ TEST_F(ve_cpuid_override, flushed_table_falls_back_to_hardware)
EXPECT_NE(r.edx & self->bit, 0u);
}
+/*
+ * The child does not block between entering the VE and the CPUID, but a
+ * tick can still preempt it there. Repeat, so that a kernel which arms
+ * faulting only at the switch has to get lucky every time.
+ */
+TEST_F(ve_cpuid_override, armed_before_first_reschedule)
+{
+ struct cpuid_regs r;
+ int i;
+
+ ASSERT_EQ(write_file_at(AT_FDCWD, CPUID_OVERRIDE_PATH, self->table), 0);
+
+ for (i = 0; i < NO_RESCHED_ROUNDS; i++) {
+ struct child_ctx ctx = { .stop = 0 };
+
+ spawn_cpuid_child(_metadata, self, &ctx);
+ collect_cpuid_child(_metadata, self, &ctx, &r);
+ ASSERT_EQ(r.edx, self->host.edx & ~self->bit)
+ TH_LOG("round %d", i);
+ }
+}
+
TEST_HARNESS_MAIN
--
2.43.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-10-06 22:14 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-06 22:12 [Devel] [PATCH hci-8.1 v4 0/5] x86/ve: CPUID override follow-ups: arm at once, prefixes, selftests Konstantin Khorenko
2026-10-06 22:12 ` [Devel] [PATCH hci-8.1 v4 1/5] selftests/ve: check CPUID override emulation for VE tasks Konstantin Khorenko
2026-10-06 22:22 ` no-reply
2026-10-06 22:12 ` [Devel] [PATCH hci-8.1 v4 2/5] x86/ve: enable CPUID faulting at once when the current task enters a VE Konstantin Khorenko
2026-10-06 22:17 ` no-reply
2026-10-06 22:12 ` Konstantin Khorenko [this message]
2026-10-06 22:18 ` [Devel] [PATCH hci-8.1 v4 3/5] selftests/ve: check CPUID override right after entering " no-reply
2026-10-06 22:12 ` [Devel] [PATCH hci-8.1 v4 4/5] x86/traps: decode the faulting CPUID with the instruction decoder Konstantin Khorenko
2026-10-06 22:19 ` no-reply
2026-10-06 22:12 ` [Devel] [PATCH hci-8.1 v4 5/5] selftests/ve: check CPUID override emulation for a prefixed CPUID Konstantin Khorenko
2026-10-06 22:19 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261007-b4-prep-khorenko-vstor-148656-cpuid-v4-3-bf16c29bea24@virtuozzo.com \
--to=khorenko@virtuozzo.com \
--cc=devel@openvz.org \
--cc=ptikhomirov@virtuozzo.com \
--cc=vasileios.almpanis@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox