1212#include "test_util.h"
1313#include "kvm_util.h"
1414#include "processor.h"
15+ #include "svm_util.h"
1516#include "vmx.h"
1617
1718/* The memory slot index to track dirty pages */
2526#define NESTED_TEST_MEM1 0xc0001000
2627#define NESTED_TEST_MEM2 0xc0002000
2728
29+ #define L2_GUEST_STACK_SIZE 64
30+
2831static void l2_guest_code (u64 * a , u64 * b )
2932{
3033 READ_ONCE (* a );
@@ -42,20 +45,19 @@ static void l2_guest_code(u64 *a, u64 *b)
4245 vmcall ();
4346}
4447
45- static void l2_guest_code_ept_enabled (void )
48+ static void l2_guest_code_tdp_enabled (void )
4649{
4750 l2_guest_code ((u64 * )NESTED_TEST_MEM1 , (u64 * )NESTED_TEST_MEM2 );
4851}
4952
50- static void l2_guest_code_ept_disabled (void )
53+ static void l2_guest_code_tdp_disabled (void )
5154{
52- /* Access the same L1 GPAs as l2_guest_code_ept_enabled () */
55+ /* Access the same L1 GPAs as l2_guest_code_tdp_enabled () */
5356 l2_guest_code ((u64 * )GUEST_TEST_MEM , (u64 * )GUEST_TEST_MEM );
5457}
5558
56- void l1_guest_code (struct vmx_pages * vmx )
59+ void l1_vmx_code (struct vmx_pages * vmx )
5760{
58- #define L2_GUEST_STACK_SIZE 64
5961 unsigned long l2_guest_stack [L2_GUEST_STACK_SIZE ];
6062 void * l2_rip ;
6163
@@ -64,22 +66,49 @@ void l1_guest_code(struct vmx_pages *vmx)
6466 GUEST_ASSERT (load_vmcs (vmx ));
6567
6668 if (vmx -> eptp_gpa )
67- l2_rip = l2_guest_code_ept_enabled ;
69+ l2_rip = l2_guest_code_tdp_enabled ;
6870 else
69- l2_rip = l2_guest_code_ept_disabled ;
71+ l2_rip = l2_guest_code_tdp_disabled ;
7072
7173 prepare_vmcs (vmx , l2_rip , & l2_guest_stack [L2_GUEST_STACK_SIZE ]);
7274
7375 GUEST_SYNC (false);
7476 GUEST_ASSERT (!vmlaunch ());
7577 GUEST_SYNC (false);
76- GUEST_ASSERT (vmreadz (VM_EXIT_REASON ) == EXIT_REASON_VMCALL );
78+ GUEST_ASSERT_EQ (vmreadz (VM_EXIT_REASON ), EXIT_REASON_VMCALL );
7779 GUEST_DONE ();
7880}
7981
80- static void test_vmx_dirty_log ( bool enable_ept )
82+ static void l1_svm_code ( struct svm_test_data * svm )
8183{
82- vm_vaddr_t vmx_pages_gva = 0 ;
84+ unsigned long l2_guest_stack [L2_GUEST_STACK_SIZE ];
85+ void * l2_rip ;
86+
87+ if (svm -> ncr3_gpa )
88+ l2_rip = l2_guest_code_tdp_enabled ;
89+ else
90+ l2_rip = l2_guest_code_tdp_disabled ;
91+
92+ generic_svm_setup (svm , l2_rip , & l2_guest_stack [L2_GUEST_STACK_SIZE ]);
93+
94+ GUEST_SYNC (false);
95+ run_guest (svm -> vmcb , svm -> vmcb_gpa );
96+ GUEST_SYNC (false);
97+ GUEST_ASSERT_EQ (svm -> vmcb -> control .exit_code , SVM_EXIT_VMMCALL );
98+ GUEST_DONE ();
99+ }
100+
101+ static void l1_guest_code (void * data )
102+ {
103+ if (this_cpu_has (X86_FEATURE_VMX ))
104+ l1_vmx_code (data );
105+ else
106+ l1_svm_code (data );
107+ }
108+
109+ static void test_dirty_log (bool nested_tdp )
110+ {
111+ vm_vaddr_t nested_gva = 0 ;
83112 unsigned long * bmap ;
84113 uint64_t * host_test_mem ;
85114
@@ -88,15 +117,19 @@ static void test_vmx_dirty_log(bool enable_ept)
88117 struct ucall uc ;
89118 bool done = false;
90119
91- pr_info ("Nested EPT : %s\n" , enable_ept ? "enabled" : "disabled" );
120+ pr_info ("Nested TDP : %s\n" , nested_tdp ? "enabled" : "disabled" );
92121
93122 /* Create VM */
94123 vm = vm_create_with_one_vcpu (& vcpu , l1_guest_code );
95- if (enable_ept )
124+ if (nested_tdp )
96125 vm_enable_tdp (vm );
97126
98- vcpu_alloc_vmx (vm , & vmx_pages_gva );
99- vcpu_args_set (vcpu , 1 , vmx_pages_gva );
127+ if (kvm_cpu_has (X86_FEATURE_VMX ))
128+ vcpu_alloc_vmx (vm , & nested_gva );
129+ else
130+ vcpu_alloc_svm (vm , & nested_gva );
131+
132+ vcpu_args_set (vcpu , 1 , nested_gva );
100133
101134 /* Add an extra memory slot for testing dirty logging */
102135 vm_userspace_mem_region_add (vm , VM_MEM_SRC_ANONYMOUS ,
@@ -115,10 +148,10 @@ static void test_vmx_dirty_log(bool enable_ept)
115148 * ... pages in the L2 GPA range [0xc0001000, 0xc0003000) will map to
116149 * 0xc0000000.
117150 *
118- * When EPT is disabled, the L2 guest code will still access the same L1
119- * GPAs as the EPT enabled case.
151+ * When TDP is disabled, the L2 guest code will still access the same L1
152+ * GPAs as the TDP enabled case.
120153 */
121- if (enable_ept ) {
154+ if (nested_tdp ) {
122155 tdp_identity_map_default_memslots (vm );
123156 tdp_map (vm , NESTED_TEST_MEM1 , GUEST_TEST_MEM , PAGE_SIZE );
124157 tdp_map (vm , NESTED_TEST_MEM2 , GUEST_TEST_MEM , PAGE_SIZE );
@@ -166,12 +199,12 @@ static void test_vmx_dirty_log(bool enable_ept)
166199
167200int main (int argc , char * argv [])
168201{
169- TEST_REQUIRE (kvm_cpu_has (X86_FEATURE_VMX ));
202+ TEST_REQUIRE (kvm_cpu_has (X86_FEATURE_VMX ) || kvm_cpu_has ( X86_FEATURE_SVM ) );
170203
171- test_vmx_dirty_log (/*enable_ept =*/ false);
204+ test_dirty_log (/*nested_tdp =*/ false);
172205
173206 if (kvm_cpu_has_tdp ())
174- test_vmx_dirty_log (/*enable_ept =*/ true);
207+ test_dirty_log (/*nested_tdp =*/ true);
175208
176209 return 0 ;
177210}
0 commit comments