* [kvm-unit-tests PATCH] nSVM: Added test for VGIF feature
@ 2021-07-22 13:17 Lara Lazier
2021-08-02 15:09 ` Sean Christopherson
0 siblings, 1 reply; 2+ messages in thread
From: Lara Lazier @ 2021-07-22 13:17 UTC (permalink / raw)
To: kvm; +Cc: Lara Lazier
When VGIF is enabled STGI executed in guest mode
sets bit 9, while CLGI clears bit 9 in the int_ctl (offset 60h)
of the VMCB.
Signed-off-by: Lara Lazier <laramglazier@gmail.com>
---
lib/x86/processor.h | 1 +
x86/svm.c | 5 ++++
x86/svm.h | 7 +++++
x86/svm_tests.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 83 insertions(+)
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 173520f..f4d1757 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -187,6 +187,7 @@ static inline bool is_intel(void)
#define X86_FEATURE_AMD_IBPB (CPUID(0x80000008, 0, EBX, 12))
#define X86_FEATURE_NPT (CPUID(0x8000000A, 0, EDX, 0))
#define X86_FEATURE_NRIPS (CPUID(0x8000000A, 0, EDX, 3))
+#define X86_FEATURE_VGIF (CPUID(0x8000000A, 0, EDX, 16))
static inline bool this_cpu_has(u64 feature)
diff --git a/x86/svm.c b/x86/svm.c
index 4eaa97e..b0096a9 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -65,6 +65,11 @@ bool default_supported(void)
return true;
}
+bool vgif_supported(void)
+{
+ return this_cpu_has(X86_FEATURE_VGIF);
+}
+
void default_prepare(struct svm_test *test)
{
vmcb_ident(vmcb);
diff --git a/x86/svm.h b/x86/svm.h
index 995b0f8..339b9f7 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -115,6 +115,12 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
#define V_IRQ_SHIFT 8
#define V_IRQ_MASK (1 << V_IRQ_SHIFT)
+#define V_GIF_ENABLED_SHIFT 25
+#define V_GIF_ENABLED_MASK (1 << V_GIF_ENABLED_SHIFT)
+
+#define V_GIF_SHIFT 9
+#define V_GIF_MASK (1 << V_GIF_SHIFT)
+
#define V_INTR_PRIO_SHIFT 16
#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
@@ -398,6 +404,7 @@ u64 *npt_get_pdpe(void);
u64 *npt_get_pml4e(void);
bool smp_supported(void);
bool default_supported(void);
+bool vgif_supported(void);
void default_prepare(struct svm_test *test);
void default_prepare_gif_clear(struct svm_test *test);
bool default_finished(struct svm_test *test);
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 3777208..7c7b19d 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -2772,6 +2772,73 @@ static void svm_vmload_vmsave(void)
vmcb->control.intercept = intercept_saved;
}
+static void prepare_vgif_enabled(struct svm_test *test)
+{
+ default_prepare(test);
+}
+
+static void test_vgif(struct svm_test *test)
+{
+ asm volatile ("vmmcall\n\tstgi\n\tvmmcall\n\tclgi\n\tvmmcall\n\t");
+
+}
+
+static bool vgif_finished(struct svm_test *test)
+{
+ switch (get_test_stage(test))
+ {
+ case 0:
+ if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+ report(false, "VMEXIT not due to vmmcall.");
+ return true;
+ }
+ vmcb->control.int_ctl |= V_GIF_ENABLED_MASK;
+ vmcb->save.rip += 3;
+ inc_test_stage(test);
+ break;
+ case 1:
+ if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+ report(false, "VMEXIT not due to vmmcall.");
+ return true;
+ }
+ if (!(vmcb->control.int_ctl & V_GIF_MASK)) {
+ report(false, "Failed to set VGIF when executing STGI.");
+ vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
+ return true;
+ }
+ report(true, "STGI set VGIF bit.");
+ vmcb->save.rip += 3;
+ inc_test_stage(test);
+ break;
+ case 2:
+ if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+ report(false, "VMEXIT not due to vmmcall.");
+ return true;
+ }
+ if (vmcb->control.int_ctl & V_GIF_MASK) {
+ report(false, "Failed to clear VGIF when executing CLGI.");
+ vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
+ return true;
+ }
+ report(true, "CLGI cleared VGIF bit.");
+ vmcb->save.rip += 3;
+ inc_test_stage(test);
+ vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
+ break;
+ default:
+ return true;
+ break;
+ }
+
+ return get_test_stage(test) == 3;
+}
+
+static bool vgif_check(struct svm_test *test)
+{
+ return get_test_stage(test) == 3;
+}
+
+
struct svm_test svm_tests[] = {
{ "null", default_supported, default_prepare,
default_prepare_gif_clear, null_test,
@@ -2882,6 +2949,9 @@ struct svm_test svm_tests[] = {
{ "host_rflags", default_supported, host_rflags_prepare,
host_rflags_prepare_gif_clear, host_rflags_test,
host_rflags_finished, host_rflags_check },
+ { "vgif", vgif_supported, prepare_vgif_enabled,
+ default_prepare_gif_clear, test_vgif, vgif_finished,
+ vgif_check },
TEST(svm_cr4_osxsave_test),
TEST(svm_guest_state_test),
TEST(svm_npt_rsvd_bits_test),
--
2.25.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [kvm-unit-tests PATCH] nSVM: Added test for VGIF feature
2021-07-22 13:17 [kvm-unit-tests PATCH] nSVM: Added test for VGIF feature Lara Lazier
@ 2021-08-02 15:09 ` Sean Christopherson
0 siblings, 0 replies; 2+ messages in thread
From: Sean Christopherson @ 2021-08-02 15:09 UTC (permalink / raw)
To: Lara Lazier; +Cc: kvm
Nit, s/Added/Add in the shortlog
On Thu, Jul 22, 2021, Lara Lazier wrote:
> When VGIF is enabled STGI executed in guest mode
> sets bit 9, while CLGI clears bit 9 in the int_ctl (offset 60h)
> of the VMCB.
>
> Signed-off-by: Lara Lazier <laramglazier@gmail.com>
> ---
...
> --- a/x86/svm_tests.c
> +++ b/x86/svm_tests.c
> @@ -2772,6 +2772,73 @@ static void svm_vmload_vmsave(void)
> vmcb->control.intercept = intercept_saved;
> }
>
> +static void prepare_vgif_enabled(struct svm_test *test)
> +{
> + default_prepare(test);
> +}
> +
> +static void test_vgif(struct svm_test *test)
> +{
> + asm volatile ("vmmcall\n\tstgi\n\tvmmcall\n\tclgi\n\tvmmcall\n\t");
While amusing, this isn't very readable :-) The SVM tests that use this for
back-to-back VMMCALL are setting a bad example. The space between "volatile" and
the opening "(" can go too.
asm volatile("vmmcall\n\t"
"stgi\n\t"
"vmmcall\n\t"
"clgi\n\t"
"vmmcall\n\t");
> +
Unnecessary newline.
> +}
> +
> +static bool vgif_finished(struct svm_test *test)
> +{
> + switch (get_test_stage(test))
> + {
> + case 0:
> + if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
> + report(false, "VMEXIT not due to vmmcall.");
> + return true;
> + }
> + vmcb->control.int_ctl |= V_GIF_ENABLED_MASK;
Setting and restoring a control flag should be done in setup/teardown, e.g. this
approach will leave V_GIF_ENABLED_MASK set if a VMMCALL check fails.
> + vmcb->save.rip += 3;
> + inc_test_stage(test);
> + break;
> + case 1:
> + if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
> + report(false, "VMEXIT not due to vmmcall.");
> + return true;
> + }
> + if (!(vmcb->control.int_ctl & V_GIF_MASK)) {
> + report(false, "Failed to set VGIF when executing STGI.");
> + vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
> + return true;
Are the VGIF checks really fatal? I.e. can we keep running of a STGI/CLGI test
fails? That would allow for slightly cleaner code.
> + }
> + report(true, "STGI set VGIF bit.");
> + vmcb->save.rip += 3;
> + inc_test_stage(test);
> + break;
> + case 2:
> + if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
> + report(false, "VMEXIT not due to vmmcall.");
> + return true;
> + }
> + if (vmcb->control.int_ctl & V_GIF_MASK) {
> + report(false, "Failed to clear VGIF when executing CLGI.");
> + vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
> + return true;
> + }
> + report(true, "CLGI cleared VGIF bit.");
> + vmcb->save.rip += 3;
> + inc_test_stage(test);
> + vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
> + break;
Something like this is more reader friendly as the boilerplate is consoliated,
abd the interesting test code is isolated in the switch statement.
bool is_vmmcall_exit = (vmcb->control.exit_code == SVM_EXIT_VMMCALL);
report(is_vmmcall_exit, ...);
if (!is_vmmcall_exit)
return true;
switch (get_test_stage())
{
case 0:
vmcb->control.int_ctl |= V_GIF_ENABLED_MASK;
break;
case 1:
report(vmcb->control.int_ctl & V_GIF_MASK, ...);
break;
case 2:
report(!(vmcb->control.int_ctl & V_GIF_MASK), ...);
break;
default:
break;
}
vmcb->save.rip += 3;
inc_test_stage(test);
return get_test_stage() >= 3;
> + default:
> + return true;
> + break;
> + }
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-08-02 15:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-22 13:17 [kvm-unit-tests PATCH] nSVM: Added test for VGIF feature Lara Lazier
2021-08-02 15:09 ` Sean Christopherson
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.