From: Sean Christopherson <seanjc@google.com>
To: Aaron Lewis <aaronlewis@google.com>
Cc: kvm@vger.kernel.org, pbonzini@redhat.com, jmattson@google.com
Subject: Re: [kvm-unit-tests PATCH 3/3] x86: Add test coverage for the routing logic when exceptions occur in L2
Date: Thu, 9 Dec 2021 21:15:02 +0000 [thread overview]
Message-ID: <YbJx1iB9ZowrVcuF@google.com> (raw)
In-Reply-To: <20211209182624.2316453-4-aaronlewis@google.com>
On Thu, Dec 09, 2021, Aaron Lewis wrote:
> +static void vmx_exception_test_guest(void)
> +{
> + handler old_gp = handle_exception(GP_VECTOR, vmx_exception_handler_gp);
> + handler old_ud = handle_exception(UD_VECTOR, vmx_exception_handler_ud);
> + handler old_de = handle_exception(DE_VECTOR, vmx_exception_handler_de);
> + handler old_db = handle_exception(DB_VECTOR, vmx_exception_handler_db);
> + handler old_bp = handle_exception(BP_VECTOR, vmx_exception_handler_bp);
> + bool raised_vector = false;
> + u64 old_cr0, old_rflags;
> +
> + asm volatile (
> + /* Return to L1 before starting the tests. */
> + "vmcall\n\t"
> +
> + /* #GP handled by L2*/
> + "mov %[val], %%cr0\n\t"
> + "vmx_exception_test_skip_gp:\n\t"
> + "vmcall\n\t"
> +
> + /* #GP handled by L1 */
> + "mov %[val], %%cr0\n\t"
I would strongly prefer each of these be a standalone subtest in the sense that
each test starts from a clean state, configures the environment as need, then
triggers the exception and checks the results. I absolutely detest the tests
that string a bunch of scenarios together, they inevitably accrue subtle dependencies
between scenarios and are generally difficult/annoying to debug.
Having a gigantic asm blob is also unnecessary. #GP can be generated with a
non-canonical access purely in C. Ditto for #AC though that may or may not be
more readable. #DE probably requires assembly to avoid compiler intervention.
#UD and #BP should be short and sweet. E.g.
It should be fairly straightforward to create a framework to handle running each
test, a la the vmx_tests array. E.g. something like the below (completely untested).
This way there's no need to skip instructions, thus no need for a exposing a bunch
of labels. Each test is isolated, there's no code pairing between L0 and L1/L2, and
adding new tests or running a specific test is trivial.
static u8 vmx_exception_test_vector;
static void vmx_exception_handler(struct ex_regs *regs)
{
report(regs->vector == vmx_exception_test_vector,
"Handling %s in L2's exception handler",
exception_mnemonic(vmx_exception_test_vector));
}
static void vmx_gp_test_guest(void)
{
*(volatile u64 *)NONCANONICAL = 0;
}
static void handle_exception_in_l2(u8 vector)
{
handler old_handler = handle_exception(vector, vmx_exception_handler);
u32 old_eb = vmcs_read(EXC_BITMAP);
vmx_exception_test_vector = vector;
vmcs_write(EXC_BITMAP, old_eb & ~(1u << vector));
enter_guest();
report(vmcs_read(EXI_REASON) == VMX_VMCALL,
"%s handled by L2", exception_mnemonic(vector));
vmcs_write(EXC_BITMAP, old_eb);
handle_exception(old_handler);
}
static void handle_exception_in_l1(u32 vector, const char *vector_name)
{
u32 old_eb = vmcs_read(EXC_BITMAP);
vmx_exception_test_vector = 0xff;
vmcs_write(EXC_BITMAP, old_eb | (1u << vector));
enter_guest();
report((vmcs_read(EXI_REASON) == VMX_EXC_NMI) &&
((vmcs_read(EXI_INTR_INFO) & 0xff) == vector),
"%s handled by L1", exception_mnemonic(vector));
vmcs_write(EXC_BITMAP, old_eb);
}
struct vmx_exception_test {
u8 vector;
void (*guest_code)(void);
}
struct vmx_exception_test vmx_exception_tests[] {
{ GP_VECTOR, vmx_gp_test_guest },
};
static void vmx_exception_test(void)
{
struct vmx_exception_test *t;
handler old_ex;
enter_guest();
assert_exit_reason(VMX_VMCALL);
skip_exit_insn();
for (i = 0; i < ARRAY_SIZE(vmx_exception_tests); i++) {
t = &vmx_exception_tests[i];
test_set_guest(t->guest_code);
handle_exception_in_l2(t->vector);
handle_exception_in_l1(t->vector);
}
}
next prev parent reply other threads:[~2021-12-09 21:15 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-09 18:26 [kvm-unit-tests PATCH 0/3] Add additional testing for routing L2 exceptions Aaron Lewis
2021-12-09 18:26 ` [kvm-unit-tests PATCH 1/3] x86: Fix a #GP from occurring in usermode's exception handlers Aaron Lewis
2021-12-09 20:04 ` Sean Christopherson
2021-12-09 18:26 ` [kvm-unit-tests PATCH 2/3] x86: Align L2's stacks Aaron Lewis
2021-12-09 20:06 ` Sean Christopherson
2021-12-09 18:26 ` [kvm-unit-tests PATCH 3/3] x86: Add test coverage for the routing logic when exceptions occur in L2 Aaron Lewis
2021-12-09 21:15 ` Sean Christopherson [this message]
2021-12-14 1:19 ` Aaron Lewis
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=YbJx1iB9ZowrVcuF@google.com \
--to=seanjc@google.com \
--cc=aaronlewis@google.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.