1 /*	$OpenBSD: vioscribble.c,v 1.4 2023/07/26 05:50:45 anton Exp $	*/
2 
3 /*
4  * Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Quick hack of a program to try to test vioqcow2.c against
21  * vioraw.c.
22  *
23  * Compile with:
24  *
25  *     cc -pthread -o scribble vioscribble.c vioqcow2.c vioraw.c
26  */
27 #include <sys/param.h>	/* PAGE_SIZE */
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 
31 #include <machine/vmmvar.h>
32 #include <dev/pci/pcireg.h>
33 #include <dev/pci/pcidevs.h>
34 #include <dev/pv/virtioreg.h>
35 #include <dev/pv/vioblkreg.h>
36 #include <dev/pv/vioscsireg.h>
37 
38 #include <net/if.h>
39 #include <netinet/in.h>
40 #include <netinet/if_ether.h>
41 
42 #include <errno.h>
43 #include <event.h>
44 #include <poll.h>
45 #include <stddef.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <pthread.h>
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <assert.h>
52 #include <err.h>
53 #include <stdarg.h>
54 #include <syslog.h>
55 
56 #include "vmd.h"
57 #include "vmm.h"
58 #include "virtio.h"
59 
60 #define CLUSTERSZ 65536
61 
62 struct virtio_backing qcowfile;
63 struct virtio_backing rawfile;
64 
65 /* We expect the scribble disks to be 4g in size */
66 #define DISKSZ	(4ull*1024ull*1024ull*1024ull)
67 
68 static void
69 fill(size_t off, char *buf, size_t len)
70 {
71 	size_t i;
72 
73 	/* use the top bits of off, since we can guess at where we went wrong. */
74 	for (i = 0; i < len; i++)
75 		buf[i] = (off >> 8);
76 }
77 
78 int
79 main(int argc, char **argv)
80 {
81 	int qcfd, rawfd, i;
82 	char buf[64*1024], cmp[64*1024];
83 	off_t len, off, qcsz, rawsz;
84 
85 	log_init(1, LOG_DAEMON);
86 
87 	qcfd = open("scribble.qcow2", O_RDWR);
88 	rawfd = open("scribble.raw", O_RDWR);
89 	if (qcfd == -1)
90 		err(1, "unable to open qcow");
91 	if (virtio_qcow2_init(&qcowfile, &qcsz, &qcfd, 1) == -1)
92 		err(1, "unable to init qcow");
93 	if (rawfd == -1 || virtio_raw_init(&rawfile, &rawsz, &rawfd, 1) == -1)
94 		err(1, "unable to open raw");
95 
96 	srandom_deterministic(123);
97 
98 	/* scribble to both disks */
99 	printf("scribbling...\n");
100 	for (i = 0; i < 1024*16; i++) {
101 		off = (random() % DISKSZ);
102 		len = random() % sizeof buf + 1;
103 		fill(off, buf, sizeof buf);
104 		if (qcowfile.pwrite(qcowfile.p, buf, len, off) == -1)
105 			printf("iter %d: unable to write at %llx\n", i, off);
106 		rawfile.pwrite(rawfile.p, buf, len, off);
107 
108 		if (qcowfile.pread(qcowfile.p, buf, len, off) == -1)
109 			printf("unable to read at %llx\n", off);
110 		rawfile.pread(rawfile.p, cmp, len, off);
111 		if (memcmp(buf, cmp, len) != 0) {
112 			printf("iter %d: mismatch at 0x%llx (espected val: %d)\n",
113 			    i, off, (char)(off  >> 8));
114 			break;
115 		}
116 	}
117 
118 	/* validate that both disks match */
119 	printf("validating...\n");
120 	for (off = 0; off < DISKSZ; off += sizeof buf) {
121 		if (qcowfile.pread(qcowfile.p, buf, sizeof buf, off) == -1)
122 			printf("unable to read at %llx\n", off);
123 		rawfile.pread(rawfile.p, cmp, sizeof buf, off);
124 		if (memcmp(buf, cmp, sizeof buf) != 0) {
125 			printf("mismatch at 0x%llx (espected val: %d)\n",
126 			    off, (char)(off  >> 8));
127 			break;
128 		}
129 	}
130 	return 0;
131 }
132