1578d9a56SPatrick Mooney /*
2578d9a56SPatrick Mooney  * This file and its contents are supplied under the terms of the
3578d9a56SPatrick Mooney  * Common Development and Distribution License ("CDDL"), version 1.0.
4578d9a56SPatrick Mooney  * You may only use this file in accordance with the terms of version
5578d9a56SPatrick Mooney  * 1.0 of the CDDL.
6578d9a56SPatrick Mooney  *
7578d9a56SPatrick Mooney  * A full copy of the text of the CDDL should have accompanied this
8578d9a56SPatrick Mooney  * source.  A copy of the CDDL is also available via the Internet at
9578d9a56SPatrick Mooney  * http://www.illumos.org/license/CDDL.
10578d9a56SPatrick Mooney  */
11578d9a56SPatrick Mooney 
12578d9a56SPatrick Mooney /*
13578d9a56SPatrick Mooney  * Copyright 2022 Oxide Computer Company
14578d9a56SPatrick Mooney  */
15578d9a56SPatrick Mooney 
16578d9a56SPatrick Mooney #include <stdio.h>
17578d9a56SPatrick Mooney #include <unistd.h>
18578d9a56SPatrick Mooney #include <stdlib.h>
19578d9a56SPatrick Mooney #include <strings.h>
20578d9a56SPatrick Mooney #include <libgen.h>
21578d9a56SPatrick Mooney #include <assert.h>
22*32640292SAndy Fiddaman #include <errno.h>
23578d9a56SPatrick Mooney 
24578d9a56SPatrick Mooney #include <sys/types.h>
25578d9a56SPatrick Mooney #include <sys/sysmacros.h>
26578d9a56SPatrick Mooney #include <sys/debug.h>
27578d9a56SPatrick Mooney #include <sys/vmm.h>
28578d9a56SPatrick Mooney #include <sys/vmm_dev.h>
29578d9a56SPatrick Mooney #include <vmmapi.h>
30578d9a56SPatrick Mooney 
31578d9a56SPatrick Mooney #include "in_guest.h"
32578d9a56SPatrick Mooney 
33578d9a56SPatrick Mooney static const struct vcpu_cpuid_entry test_entries[] = {
34578d9a56SPatrick Mooney 	{
35578d9a56SPatrick Mooney 		.vce_function = 0,
36578d9a56SPatrick Mooney 		.vce_eax = 5,
37578d9a56SPatrick Mooney 		.vce_ebx = 0x74737552,
38578d9a56SPatrick Mooney 		.vce_edx = 0x4f206465,
39578d9a56SPatrick Mooney 		.vce_ecx = 0x65646978,
40578d9a56SPatrick Mooney 	},
41578d9a56SPatrick Mooney 	/* basic "std" leaf */
42578d9a56SPatrick Mooney 	{
43578d9a56SPatrick Mooney 		.vce_function = 1,
44578d9a56SPatrick Mooney 		.vce_eax = 0x100,
45578d9a56SPatrick Mooney 	},
46578d9a56SPatrick Mooney 
47578d9a56SPatrick Mooney 	/* skip 2 for a hole */
48578d9a56SPatrick Mooney 
49578d9a56SPatrick Mooney 	/* leaf with index matching */
50578d9a56SPatrick Mooney 	{
51578d9a56SPatrick Mooney 		.vce_function = 3,
52578d9a56SPatrick Mooney 		.vce_index = 0,
53578d9a56SPatrick Mooney 		.vce_flags = VCE_FLAG_MATCH_INDEX,
54578d9a56SPatrick Mooney 		.vce_eax = 0x300,
55578d9a56SPatrick Mooney 	},
56578d9a56SPatrick Mooney 	{
57578d9a56SPatrick Mooney 		.vce_function = 3,
58578d9a56SPatrick Mooney 		.vce_index = 1,
59578d9a56SPatrick Mooney 		.vce_flags = VCE_FLAG_MATCH_INDEX,
60578d9a56SPatrick Mooney 		.vce_eax = 0x301,
61578d9a56SPatrick Mooney 	},
62578d9a56SPatrick Mooney 
63578d9a56SPatrick Mooney 	/* leaf with index matching and a hole */
64578d9a56SPatrick Mooney 	{
65578d9a56SPatrick Mooney 		.vce_function = 4,
66578d9a56SPatrick Mooney 		.vce_index = 0,
67578d9a56SPatrick Mooney 		.vce_flags = VCE_FLAG_MATCH_INDEX,
68578d9a56SPatrick Mooney 		.vce_eax = 0x400,
69578d9a56SPatrick Mooney 	},
70578d9a56SPatrick Mooney 	{
71578d9a56SPatrick Mooney 		.vce_function = 4,
72578d9a56SPatrick Mooney 		.vce_index = 2,
73578d9a56SPatrick Mooney 		.vce_flags = VCE_FLAG_MATCH_INDEX,
74578d9a56SPatrick Mooney 		.vce_eax = 0x402,
75578d9a56SPatrick Mooney 	},
76578d9a56SPatrick Mooney 
77578d9a56SPatrick Mooney 	/* terminal "std" leaf */
78578d9a56SPatrick Mooney 	{
79578d9a56SPatrick Mooney 		.vce_function = 5,
80578d9a56SPatrick Mooney 		.vce_eax = 5,
81578d9a56SPatrick Mooney 		.vce_ebx = 5,
82578d9a56SPatrick Mooney 		.vce_edx = 5,
83578d9a56SPatrick Mooney 		.vce_ecx = 5,
84578d9a56SPatrick Mooney 	},
85578d9a56SPatrick Mooney 
86578d9a56SPatrick Mooney 	/* base "extended" leaf */
87578d9a56SPatrick Mooney 	{
88578d9a56SPatrick Mooney 		.vce_function = 0x80000000,
89578d9a56SPatrick Mooney 		.vce_eax = 0x80000001,
90578d9a56SPatrick Mooney 	},
91578d9a56SPatrick Mooney 	/* index-match "extended" leaves */
92578d9a56SPatrick Mooney 	{
93578d9a56SPatrick Mooney 		.vce_function = 0x80000001,
94578d9a56SPatrick Mooney 		.vce_index = 0x0,
95578d9a56SPatrick Mooney 		.vce_flags = VCE_FLAG_MATCH_INDEX,
96578d9a56SPatrick Mooney 		.vce_eax = 0x8000,
97578d9a56SPatrick Mooney 	},
98578d9a56SPatrick Mooney 	{
99578d9a56SPatrick Mooney 		.vce_function = 0x80000001,
100578d9a56SPatrick Mooney 		.vce_index = 0x1,
101578d9a56SPatrick Mooney 		.vce_flags = VCE_FLAG_MATCH_INDEX,
102578d9a56SPatrick Mooney 		.vce_eax = 0x8001,
103578d9a56SPatrick Mooney 	},
104578d9a56SPatrick Mooney };
105578d9a56SPatrick Mooney 
106578d9a56SPatrick Mooney int
main(int argc,char * argv[])107578d9a56SPatrick Mooney main(int argc, char *argv[])
108578d9a56SPatrick Mooney {
109578d9a56SPatrick Mooney 	const char *test_suite_name = basename(argv[0]);
110578d9a56SPatrick Mooney 	struct vmctx *ctx = NULL;
111*32640292SAndy Fiddaman 	struct vcpu *vcpu;
112578d9a56SPatrick Mooney 	int err;
113578d9a56SPatrick Mooney 
114578d9a56SPatrick Mooney 	ctx = test_initialize(test_suite_name);
115578d9a56SPatrick Mooney 
116*32640292SAndy Fiddaman 	if ((vcpu = vm_vcpu_open(ctx, 0)) == NULL) {
117*32640292SAndy Fiddaman 		test_fail_errno(errno, "Could not open vcpu0");
118*32640292SAndy Fiddaman 	}
119*32640292SAndy Fiddaman 
120*32640292SAndy Fiddaman 	err = test_setup_vcpu(vcpu, MEM_LOC_PAYLOAD, MEM_LOC_STACK);
121578d9a56SPatrick Mooney 	if (err != 0) {
122578d9a56SPatrick Mooney 		test_fail_errno(err, "Could not initialize vcpu0");
123578d9a56SPatrick Mooney 	}
124578d9a56SPatrick Mooney 
125578d9a56SPatrick Mooney 
126578d9a56SPatrick Mooney 	/* Start with test data using Intel-style fallback */
127578d9a56SPatrick Mooney 	int vmfd = vm_get_device_fd(ctx);
128578d9a56SPatrick Mooney 
129578d9a56SPatrick Mooney 	struct vm_vcpu_cpuid_config cfg = {
130578d9a56SPatrick Mooney 		.vvcc_vcpuid = 0,
131578d9a56SPatrick Mooney 		.vvcc_flags = VCC_FLAG_INTEL_FALLBACK,
132578d9a56SPatrick Mooney 		.vvcc_nent = ARRAY_SIZE(test_entries),
133578d9a56SPatrick Mooney 		/* We trust the ioctl not to alter this const value */
134578d9a56SPatrick Mooney 		.vvcc_entries = (struct vcpu_cpuid_entry *)test_entries,
135578d9a56SPatrick Mooney 	};
136578d9a56SPatrick Mooney 	err = ioctl(vmfd, VM_SET_CPUID, &cfg);
137578d9a56SPatrick Mooney 	if (err != 0) {
138578d9a56SPatrick Mooney 		test_fail_errno(err, "ioctl(VM_SET_CPUID) failed");
139578d9a56SPatrick Mooney 	}
140578d9a56SPatrick Mooney 
141578d9a56SPatrick Mooney 	struct vm_entry ventry = { 0 };
142578d9a56SPatrick Mooney 	struct vm_exit vexit = { 0 };
143578d9a56SPatrick Mooney 
144578d9a56SPatrick Mooney 	do {
145578d9a56SPatrick Mooney 		const enum vm_exit_kind kind =
146*32640292SAndy Fiddaman 		    test_run_vcpu(vcpu, &ventry, &vexit);
147578d9a56SPatrick Mooney 		switch (kind) {
148578d9a56SPatrick Mooney 		case VEK_REENTR:
149578d9a56SPatrick Mooney 			break;
150578d9a56SPatrick Mooney 		case VEK_TEST_PASS:
151578d9a56SPatrick Mooney 			test_pass();
152578d9a56SPatrick Mooney 			break;
153578d9a56SPatrick Mooney 		case VEK_TEST_FAIL:
154578d9a56SPatrick Mooney 			test_fail_msg("failed result %rip: %x", vexit.rip);
155578d9a56SPatrick Mooney 			break;
156578d9a56SPatrick Mooney 		case VEK_UNHANDLED: {
157578d9a56SPatrick Mooney 			uint32_t val;
158578d9a56SPatrick Mooney 			if (vexit_match_inout(&vexit, false, IOP_TEST_VALUE, 4,
159578d9a56SPatrick Mooney 			    &val)) {
160578d9a56SPatrick Mooney 				/*
161578d9a56SPatrick Mooney 				 * The payload has requested switch to AMD-style
162578d9a56SPatrick Mooney 				 * fallback to run the second half of the test.
163578d9a56SPatrick Mooney 				 */
164578d9a56SPatrick Mooney 				cfg.vvcc_flags = 0;
165578d9a56SPatrick Mooney 				err = ioctl(vmfd, VM_SET_CPUID, &cfg);
166578d9a56SPatrick Mooney 				if (err != 0) {
167578d9a56SPatrick Mooney 					test_fail_errno(err,
168578d9a56SPatrick Mooney 					    "ioctl(VM_SET_CPUID) failed");
169578d9a56SPatrick Mooney 				}
170578d9a56SPatrick Mooney 				ventry_fulfill_inout(&vexit, &ventry, 0);
171578d9a56SPatrick Mooney 			} else {
172578d9a56SPatrick Mooney 				test_fail_vmexit(&vexit);
173578d9a56SPatrick Mooney 			}
174578d9a56SPatrick Mooney 			break;
175578d9a56SPatrick Mooney 		}
176578d9a56SPatrick Mooney 
177578d9a56SPatrick Mooney 		default:
178578d9a56SPatrick Mooney 			test_fail_vmexit(&vexit);
179578d9a56SPatrick Mooney 			break;
180578d9a56SPatrick Mooney 		}
181578d9a56SPatrick Mooney 	} while (true);
182578d9a56SPatrick Mooney }
183