@@ -34,6 +34,8 @@ static inline void rdmsr_from_l2(uint32_t msr)
34
34
35
35
void l2_guest_code (void )
36
36
{
37
+ u64 unused ;
38
+
37
39
GUEST_SYNC (3 );
38
40
/* Exit to L1 */
39
41
vmmcall ();
@@ -47,25 +49,52 @@ void l2_guest_code(void)
47
49
48
50
GUEST_SYNC (5 );
49
51
52
+ /* L2 TLB flush tests */
53
+ hyperv_hypercall (HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE |
54
+ HV_HYPERCALL_FAST_BIT , 0x0 ,
55
+ HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES |
56
+ HV_FLUSH_ALL_PROCESSORS );
57
+ rdmsr_from_l2 (MSR_FS_BASE );
58
+ /*
59
+ * Note: hypercall status (RAX) is not preserved correctly by L1 after
60
+ * synthetic vmexit, use unchecked version.
61
+ */
62
+ __hyperv_hypercall (HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE |
63
+ HV_HYPERCALL_FAST_BIT , 0x0 ,
64
+ HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES |
65
+ HV_FLUSH_ALL_PROCESSORS , & unused );
66
+
50
67
/* Done, exit to L1 and never come back. */
51
68
vmmcall ();
52
69
}
53
70
54
- static void __attribute__((__flatten__ )) guest_code (struct svm_test_data * svm )
71
+ static void __attribute__((__flatten__ )) guest_code (struct svm_test_data * svm ,
72
+ struct hyperv_test_pages * hv_pages ,
73
+ vm_vaddr_t pgs_gpa )
55
74
{
56
75
unsigned long l2_guest_stack [L2_GUEST_STACK_SIZE ];
57
76
struct vmcb * vmcb = svm -> vmcb ;
58
77
struct hv_vmcb_enlightenments * hve = & vmcb -> control .hv_enlightenments ;
59
78
60
79
GUEST_SYNC (1 );
61
80
62
- wrmsr (HV_X64_MSR_GUEST_OS_ID , (u64 )0x8100 << 48 );
81
+ wrmsr (HV_X64_MSR_GUEST_OS_ID , HYPERV_LINUX_OS_ID );
82
+ wrmsr (HV_X64_MSR_HYPERCALL , pgs_gpa );
83
+ enable_vp_assist (hv_pages -> vp_assist_gpa , hv_pages -> vp_assist );
63
84
64
85
GUEST_ASSERT (svm -> vmcb_gpa );
65
86
/* Prepare for L2 execution. */
66
87
generic_svm_setup (svm , l2_guest_code ,
67
88
& l2_guest_stack [L2_GUEST_STACK_SIZE ]);
68
89
90
+ /* L2 TLB flush setup */
91
+ hve -> partition_assist_page = hv_pages -> partition_assist_gpa ;
92
+ hve -> hv_enlightenments_control .nested_flush_hypercall = 1 ;
93
+ hve -> hv_vm_id = 1 ;
94
+ hve -> hv_vp_id = 1 ;
95
+ current_vp_assist -> nested_control .features .directhypercall = 1 ;
96
+ * (u32 * )(hv_pages -> partition_assist ) = 0 ;
97
+
69
98
GUEST_SYNC (2 );
70
99
run_guest (vmcb , svm -> vmcb_gpa );
71
100
GUEST_ASSERT (vmcb -> control .exit_code == SVM_EXIT_VMMCALL );
@@ -100,6 +129,20 @@ static void __attribute__((__flatten__)) guest_code(struct svm_test_data *svm)
100
129
GUEST_ASSERT (vmcb -> control .exit_code == SVM_EXIT_MSR );
101
130
vmcb -> save .rip += 2 ; /* rdmsr */
102
131
132
+
133
+ /*
134
+ * L2 TLB flush test. First VMCALL should be handled directly by L0,
135
+ * no VMCALL exit expected.
136
+ */
137
+ run_guest (vmcb , svm -> vmcb_gpa );
138
+ GUEST_ASSERT (vmcb -> control .exit_code == SVM_EXIT_MSR );
139
+ vmcb -> save .rip += 2 ; /* rdmsr */
140
+ /* Enable synthetic vmexit */
141
+ * (u32 * )(hv_pages -> partition_assist ) = 1 ;
142
+ run_guest (vmcb , svm -> vmcb_gpa );
143
+ GUEST_ASSERT (vmcb -> control .exit_code == HV_SVM_EXITCODE_ENL );
144
+ GUEST_ASSERT (vmcb -> control .exit_info_1 == HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH );
145
+
103
146
run_guest (vmcb , svm -> vmcb_gpa );
104
147
GUEST_ASSERT (vmcb -> control .exit_code == SVM_EXIT_VMMCALL );
105
148
GUEST_SYNC (6 );
@@ -109,8 +152,8 @@ static void __attribute__((__flatten__)) guest_code(struct svm_test_data *svm)
109
152
110
153
int main (int argc , char * argv [])
111
154
{
112
- vm_vaddr_t nested_gva = 0 ;
113
-
155
+ vm_vaddr_t nested_gva = 0 , hv_pages_gva = 0 ;
156
+ vm_vaddr_t hcall_page ;
114
157
struct kvm_vcpu * vcpu ;
115
158
struct kvm_vm * vm ;
116
159
struct kvm_run * run ;
@@ -124,7 +167,13 @@ int main(int argc, char *argv[])
124
167
vcpu_set_hv_cpuid (vcpu );
125
168
run = vcpu -> run ;
126
169
vcpu_alloc_svm (vm , & nested_gva );
127
- vcpu_args_set (vcpu , 1 , nested_gva );
170
+ vcpu_alloc_hyperv_test_pages (vm , & hv_pages_gva );
171
+
172
+ hcall_page = vm_vaddr_alloc_pages (vm , 1 );
173
+ memset (addr_gva2hva (vm , hcall_page ), 0x0 , getpagesize ());
174
+
175
+ vcpu_args_set (vcpu , 3 , nested_gva , hv_pages_gva , addr_gva2gpa (vm , hcall_page ));
176
+ vcpu_set_msr (vcpu , HV_X64_MSR_VP_INDEX , vcpu -> id );
128
177
129
178
for (stage = 1 ;; stage ++ ) {
130
179
vcpu_run (vcpu );
0 commit comments