1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2022 Oxide Computer Company
14  */
15 
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <libgen.h>
21 #include <sys/stat.h>
22 #include <errno.h>
23 #include <err.h>
24 #include <assert.h>
25 
26 #include <sys/vmm.h>
27 #include <sys/vmm_dev.h>
28 #include <vmmapi.h>
29 
30 #include "common.h"
31 
32 int
main(int argc,char * argv[])33 main(int argc, char *argv[])
34 {
35 	const char *suite_name = basename(argv[0]);
36 	struct vmctx *ctx;
37 	struct vcpu *vcpu;
38 
39 	ctx = create_test_vm(suite_name);
40 	if (ctx == NULL) {
41 		errx(EXIT_FAILURE, "could open test VM");
42 	}
43 
44 	/*
45 	 * It would be odd if we had the freshly created VM instance, but it did
46 	 * not appear to exist.
47 	 */
48 	assert(check_instance_usable(suite_name));
49 
50 	if ((vcpu = vm_vcpu_open(ctx, 0)) == NULL) {
51 		err(EXIT_FAILURE, "Could not open vcpu0");
52 	}
53 
54 	/* Ensure sure that auto-destruct is off */
55 	if (ioctl(vm_get_device_fd(ctx), VM_SET_AUTODESTRUCT, 0) != 0) {
56 		errx(EXIT_FAILURE, "could not disable auto-destruct");
57 	}
58 
59 	if (ioctl(vm_get_device_fd(ctx), VM_DESTROY_SELF, 0) != 0) {
60 		errx(EXIT_FAILURE, "ioctl(VM_DESTROY_SELF) failed");
61 	}
62 
63 	/*
64 	 * Since we still hold the instance open, we expect it to still exist in
65 	 * /dev/vmm, but be useless for further operations
66 	 */
67 	if (!check_instance_exists(suite_name)) {
68 		err(EXIT_FAILURE,
69 		    "instance missing after unfinished destroy");
70 	}
71 
72 	/* Attempt an operation on our still-open handle */
73 	uint64_t reg = 0;
74 	if (vm_get_register(vcpu, VM_REG_GUEST_RAX, &reg) == 0) {
75 		err(EXIT_FAILURE,
76 		    "VM_GET_REGISTER succeeded despite instance destruction");
77 	}
78 	/* Check usability via the dedicated ioctl */
79 	if (check_instance_usable(suite_name)) {
80 		err(EXIT_FAILURE,
81 		    "instance not reporting in-progress destruction");
82 	}
83 
84 
85 	vm_vcpu_close(vcpu);
86 	vm_close(ctx);
87 	ctx = NULL;
88 
89 	/* Make doubly-sure the VM is gone after close */
90 	if (check_instance_exists(suite_name)) {
91 		err(EXIT_FAILURE, "instance still accessible after destroy");
92 	}
93 
94 	(void) printf("%s\tPASS\n", suite_name);
95 	return (EXIT_SUCCESS);
96 }
97