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
62struct virtio_backing qcowfile;
63struct virtio_backing rawfile;
64
65/* We expect the scribble disks to be 4g in size */
66#define DISKSZ	(4ull*1024ull*1024ull*1024ull)
67
68static void
69fill(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
78int
79main(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