0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "test_util.h"
0011 #include "kvm_util.h"
0012 #include "processor.h"
0013 #include "vmx.h"
0014
0015 #include <errno.h>
0016 #include <linux/kvm.h>
0017 #include <string.h>
0018 #include <sys/ioctl.h>
0019 #include <unistd.h>
0020
0021
0022
0023
0024
0025 #define VMCS12_REVISION 0x11e57ed0
0026
0027 bool have_evmcs;
0028
0029 void test_nested_state(struct kvm_vcpu *vcpu, struct kvm_nested_state *state)
0030 {
0031 vcpu_nested_state_set(vcpu, state);
0032 }
0033
0034 void test_nested_state_expect_errno(struct kvm_vcpu *vcpu,
0035 struct kvm_nested_state *state,
0036 int expected_errno)
0037 {
0038 int rv;
0039
0040 rv = __vcpu_nested_state_set(vcpu, state);
0041 TEST_ASSERT(rv == -1 && errno == expected_errno,
0042 "Expected %s (%d) from vcpu_nested_state_set but got rv: %i errno: %s (%d)",
0043 strerror(expected_errno), expected_errno, rv, strerror(errno),
0044 errno);
0045 }
0046
0047 void test_nested_state_expect_einval(struct kvm_vcpu *vcpu,
0048 struct kvm_nested_state *state)
0049 {
0050 test_nested_state_expect_errno(vcpu, state, EINVAL);
0051 }
0052
0053 void test_nested_state_expect_efault(struct kvm_vcpu *vcpu,
0054 struct kvm_nested_state *state)
0055 {
0056 test_nested_state_expect_errno(vcpu, state, EFAULT);
0057 }
0058
0059 void set_revision_id_for_vmcs12(struct kvm_nested_state *state,
0060 u32 vmcs12_revision)
0061 {
0062
0063 memcpy(&state->data, &vmcs12_revision, sizeof(u32));
0064 }
0065
0066 void set_default_state(struct kvm_nested_state *state)
0067 {
0068 memset(state, 0, sizeof(*state));
0069 state->flags = KVM_STATE_NESTED_RUN_PENDING |
0070 KVM_STATE_NESTED_GUEST_MODE;
0071 state->format = 0;
0072 state->size = sizeof(*state);
0073 }
0074
0075 void set_default_vmx_state(struct kvm_nested_state *state, int size)
0076 {
0077 memset(state, 0, size);
0078 if (have_evmcs)
0079 state->flags = KVM_STATE_NESTED_EVMCS;
0080 state->format = 0;
0081 state->size = size;
0082 state->hdr.vmx.vmxon_pa = 0x1000;
0083 state->hdr.vmx.vmcs12_pa = 0x2000;
0084 state->hdr.vmx.smm.flags = 0;
0085 set_revision_id_for_vmcs12(state, VMCS12_REVISION);
0086 }
0087
0088 void test_vmx_nested_state(struct kvm_vcpu *vcpu)
0089 {
0090
0091 const int state_sz = sizeof(struct kvm_nested_state) + getpagesize();
0092 struct kvm_nested_state *state =
0093 (struct kvm_nested_state *)malloc(state_sz);
0094
0095
0096 set_default_vmx_state(state, state_sz);
0097 state->format = 1;
0098 test_nested_state_expect_einval(vcpu, state);
0099
0100
0101
0102
0103
0104 set_default_vmx_state(state, state_sz);
0105 test_nested_state_expect_einval(vcpu, state);
0106
0107
0108
0109
0110
0111
0112 set_default_vmx_state(state, state_sz);
0113 state->hdr.vmx.vmxon_pa = -1ull;
0114 test_nested_state_expect_einval(vcpu, state);
0115
0116 state->hdr.vmx.vmcs12_pa = -1ull;
0117 state->flags = KVM_STATE_NESTED_EVMCS;
0118 test_nested_state_expect_einval(vcpu, state);
0119
0120 state->flags = 0;
0121 test_nested_state(vcpu, state);
0122
0123
0124 vcpu_set_cpuid_feature(vcpu, X86_FEATURE_VMX);
0125
0126
0127
0128
0129
0130
0131
0132 set_default_vmx_state(state, state_sz);
0133 state->hdr.vmx.vmxon_pa = -1ull;
0134 state->hdr.vmx.vmcs12_pa = -1ull;
0135 test_nested_state_expect_einval(vcpu, state);
0136
0137 state->flags &= KVM_STATE_NESTED_EVMCS;
0138 if (have_evmcs) {
0139 test_nested_state_expect_einval(vcpu, state);
0140 vcpu_enable_evmcs(vcpu);
0141 }
0142 test_nested_state(vcpu, state);
0143
0144
0145 state->hdr.vmx.smm.flags = 1;
0146 test_nested_state_expect_einval(vcpu, state);
0147
0148
0149 set_default_vmx_state(state, state_sz);
0150 state->hdr.vmx.flags = ~0;
0151 test_nested_state_expect_einval(vcpu, state);
0152
0153
0154 set_default_vmx_state(state, state_sz);
0155 state->hdr.vmx.vmxon_pa = -1ull;
0156 state->flags = 0;
0157 test_nested_state_expect_einval(vcpu, state);
0158
0159
0160 set_default_vmx_state(state, state_sz);
0161 state->hdr.vmx.vmxon_pa = 1;
0162 test_nested_state_expect_einval(vcpu, state);
0163
0164
0165
0166
0167
0168 set_default_vmx_state(state, state_sz);
0169 state->flags = KVM_STATE_NESTED_GUEST_MODE |
0170 KVM_STATE_NESTED_RUN_PENDING;
0171 state->hdr.vmx.smm.flags = KVM_STATE_NESTED_SMM_GUEST_MODE;
0172 test_nested_state_expect_einval(vcpu, state);
0173
0174
0175
0176
0177
0178
0179 set_default_vmx_state(state, state_sz);
0180 state->hdr.vmx.smm.flags = ~(KVM_STATE_NESTED_SMM_GUEST_MODE |
0181 KVM_STATE_NESTED_SMM_VMXON);
0182 test_nested_state_expect_einval(vcpu, state);
0183
0184
0185 set_default_vmx_state(state, state_sz);
0186 state->flags = 0;
0187 state->hdr.vmx.smm.flags = KVM_STATE_NESTED_SMM_GUEST_MODE;
0188 test_nested_state_expect_einval(vcpu, state);
0189
0190
0191
0192
0193
0194 set_default_vmx_state(state, state_sz);
0195 state->size = sizeof(*state);
0196 state->flags = 0;
0197 test_nested_state_expect_einval(vcpu, state);
0198
0199 set_default_vmx_state(state, state_sz);
0200 state->size = sizeof(*state);
0201 state->flags = 0;
0202 state->hdr.vmx.vmcs12_pa = -1;
0203 test_nested_state(vcpu, state);
0204
0205
0206
0207
0208
0209 set_default_vmx_state(state, state_sz);
0210 state->flags = 0;
0211 test_nested_state(vcpu, state);
0212
0213
0214 set_default_vmx_state(state, state_sz);
0215 state->size = sizeof(*state);
0216 state->flags = 0;
0217 state->hdr.vmx.vmcs12_pa = -1;
0218 state->hdr.vmx.flags = ~0;
0219 test_nested_state_expect_einval(vcpu, state);
0220
0221
0222 set_default_vmx_state(state, state_sz);
0223 state->hdr.vmx.vmxon_pa = 0;
0224 state->hdr.vmx.vmcs12_pa = 0;
0225 test_nested_state_expect_einval(vcpu, state);
0226
0227
0228
0229
0230
0231 set_default_vmx_state(state, state_sz);
0232 state->hdr.vmx.vmxon_pa = -1ull;
0233 state->hdr.vmx.vmcs12_pa = -1ull;
0234 state->flags = 0;
0235 test_nested_state(vcpu, state);
0236 vcpu_nested_state_get(vcpu, state);
0237 TEST_ASSERT(state->size >= sizeof(*state) && state->size <= state_sz,
0238 "Size must be between %ld and %d. The size returned was %d.",
0239 sizeof(*state), state_sz, state->size);
0240 TEST_ASSERT(state->hdr.vmx.vmxon_pa == -1ull, "vmxon_pa must be -1ull.");
0241 TEST_ASSERT(state->hdr.vmx.vmcs12_pa == -1ull, "vmcs_pa must be -1ull.");
0242
0243 free(state);
0244 }
0245
0246 int main(int argc, char *argv[])
0247 {
0248 struct kvm_vm *vm;
0249 struct kvm_nested_state state;
0250 struct kvm_vcpu *vcpu;
0251
0252 have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS);
0253
0254 TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE));
0255
0256
0257
0258
0259
0260 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
0261
0262 vm = vm_create_with_one_vcpu(&vcpu, NULL);
0263
0264
0265
0266
0267 vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_VMX);
0268
0269
0270 test_nested_state_expect_efault(vcpu, NULL);
0271
0272
0273 set_default_state(&state);
0274 state.size = 0;
0275 test_nested_state_expect_einval(vcpu, &state);
0276
0277
0278
0279
0280
0281
0282
0283
0284 set_default_state(&state);
0285 state.flags = 0xf;
0286 test_nested_state_expect_einval(vcpu, &state);
0287
0288
0289
0290
0291
0292 set_default_state(&state);
0293 state.flags = KVM_STATE_NESTED_RUN_PENDING;
0294 test_nested_state_expect_einval(vcpu, &state);
0295
0296 test_vmx_nested_state(vcpu);
0297
0298 kvm_vm_free(vm);
0299 return 0;
0300 }