xref: /openbsd/usr.sbin/ldomd/ldomd.c (revision 34574250)
1*34574250Skettenis /*	$OpenBSD: ldomd.c,v 1.5 2012/11/04 17:37:10 kettenis Exp $	*/
2df17ef41Skettenis 
3df17ef41Skettenis /*
4df17ef41Skettenis  * Copyright (c) 2012 Mark Kettenis
5df17ef41Skettenis  *
6df17ef41Skettenis  * Permission to use, copy, modify, and distribute this software for any
7df17ef41Skettenis  * purpose with or without fee is hereby granted, provided that the above
8df17ef41Skettenis  * copyright notice and this permission notice appear in all copies.
9df17ef41Skettenis  *
10df17ef41Skettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11df17ef41Skettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12df17ef41Skettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13df17ef41Skettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14df17ef41Skettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15df17ef41Skettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16df17ef41Skettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17df17ef41Skettenis  */
18df17ef41Skettenis 
19df17ef41Skettenis #include <sys/types.h>
20df17ef41Skettenis #include <sys/ioctl.h>
21df17ef41Skettenis #include <assert.h>
22df17ef41Skettenis #include <err.h>
239f8bb9a5Skettenis #include <errno.h>
24df17ef41Skettenis #include <fcntl.h>
259f8bb9a5Skettenis #include <stdarg.h>
26df17ef41Skettenis #include <stdlib.h>
27df17ef41Skettenis #include <stdio.h>
28df17ef41Skettenis #include <string.h>
299f8bb9a5Skettenis #include <syslog.h>
30df17ef41Skettenis #include <unistd.h>
31df17ef41Skettenis 
32df17ef41Skettenis #include "ds.h"
33*34574250Skettenis #include "hvctl.h"
34df17ef41Skettenis #include "mdesc.h"
35df17ef41Skettenis #include "util.h"
36be8be80fSkettenis #include "ldomd.h"
37df17ef41Skettenis 
38df17ef41Skettenis TAILQ_HEAD(guest_head, guest) guests;
39df17ef41Skettenis 
40df17ef41Skettenis void add_guest(struct md_node *);
41be8be80fSkettenis void map_domain_services(struct md *);
42df17ef41Skettenis 
43df17ef41Skettenis void frag_init(void);
44df17ef41Skettenis void add_frag_mblock(struct md_node *);
45df17ef41Skettenis void add_frag(uint64_t);
46df17ef41Skettenis void delete_frag(uint64_t);
47df17ef41Skettenis uint64_t alloc_frag(void);
48df17ef41Skettenis 
49df17ef41Skettenis void hv_update_md(struct guest *guest);
50ee8d39aaSkettenis void hv_open(void);
51ee8d39aaSkettenis void hv_close(void);
529f8bb9a5Skettenis void hv_read(uint64_t, void *, size_t);
53df17ef41Skettenis void hv_write(uint64_t, void *, size_t);
54df17ef41Skettenis 
55df17ef41Skettenis int hvctl_seq = 1;
56df17ef41Skettenis int hvctl_fd;
57df17ef41Skettenis 
58df17ef41Skettenis void *hvmd_buf;
59df17ef41Skettenis size_t hvmd_len;
60df17ef41Skettenis struct md *hvmd;
61df17ef41Skettenis uint64_t hv_mdpa;
62df17ef41Skettenis 
639f8bb9a5Skettenis __dead void	usage(void);
649f8bb9a5Skettenis void	logit(int, const char *, ...);
659f8bb9a5Skettenis void	vlog(int, const char *, va_list);
669f8bb9a5Skettenis 
679f8bb9a5Skettenis void
689f8bb9a5Skettenis log_init(int n_debug)
699f8bb9a5Skettenis {
709f8bb9a5Skettenis 	extern char *__progname;
719f8bb9a5Skettenis 
729f8bb9a5Skettenis 	debug = n_debug;
739f8bb9a5Skettenis 
749f8bb9a5Skettenis 	if (!debug)
759f8bb9a5Skettenis 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
769f8bb9a5Skettenis 
779f8bb9a5Skettenis 	tzset();
789f8bb9a5Skettenis }
799f8bb9a5Skettenis 
809f8bb9a5Skettenis void
819f8bb9a5Skettenis fatal(const char *emsg)
829f8bb9a5Skettenis {
839f8bb9a5Skettenis 	if (errno)
849f8bb9a5Skettenis 		logit(LOG_CRIT, "fatal: %s: %s\n", emsg, strerror(errno));
859f8bb9a5Skettenis 	else
869f8bb9a5Skettenis 		logit(LOG_CRIT, "fatal: %s\n", emsg);
879f8bb9a5Skettenis 
889f8bb9a5Skettenis 	exit(EXIT_FAILURE);
899f8bb9a5Skettenis }
909f8bb9a5Skettenis 
919f8bb9a5Skettenis void
929f8bb9a5Skettenis logit(int pri, const char *fmt, ...)
939f8bb9a5Skettenis {
949f8bb9a5Skettenis 	va_list ap;
959f8bb9a5Skettenis 
969f8bb9a5Skettenis 	va_start(ap, fmt);
979f8bb9a5Skettenis 	vlog(pri, fmt, ap);
989f8bb9a5Skettenis 	va_end(ap);
999f8bb9a5Skettenis }
1009f8bb9a5Skettenis 
1019f8bb9a5Skettenis void
1029f8bb9a5Skettenis vlog(int pri, const char *fmt, va_list ap)
1039f8bb9a5Skettenis {
1049f8bb9a5Skettenis 	char *nfmt;
1059f8bb9a5Skettenis 
1069f8bb9a5Skettenis 	if (debug) {
1079f8bb9a5Skettenis 		/* best effort in out of mem situations */
1089f8bb9a5Skettenis 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
1099f8bb9a5Skettenis 			vfprintf(stderr, fmt, ap);
1109f8bb9a5Skettenis 			fprintf(stderr, "\n");
1119f8bb9a5Skettenis 		} else {
1129f8bb9a5Skettenis 			vfprintf(stderr, nfmt, ap);
1139f8bb9a5Skettenis 			free(nfmt);
1149f8bb9a5Skettenis 		}
1159f8bb9a5Skettenis 		fflush(stderr);
1169f8bb9a5Skettenis 	} else
1179f8bb9a5Skettenis 		vsyslog(pri, fmt, ap);
1189f8bb9a5Skettenis }
1199f8bb9a5Skettenis 
120df17ef41Skettenis int
121df17ef41Skettenis main(int argc, char **argv)
122df17ef41Skettenis {
123df17ef41Skettenis 	struct hvctl_msg msg;
124df17ef41Skettenis 	ssize_t nbytes;
125df17ef41Skettenis 	struct md_header hdr;
126df17ef41Skettenis 	struct md_node *node;
127df17ef41Skettenis 	struct md_prop *prop;
128be8be80fSkettenis 	struct guest *guest;
1299f8bb9a5Skettenis 	int debug = 0;
1309f8bb9a5Skettenis 	int ch;
1319f8bb9a5Skettenis 
1329f8bb9a5Skettenis 	log_init(1);
1339f8bb9a5Skettenis 
1349f8bb9a5Skettenis 	while ((ch = getopt(argc, argv, "d")) != -1) {
1359f8bb9a5Skettenis 		switch (ch) {
1369f8bb9a5Skettenis 		case 'd':
1379f8bb9a5Skettenis 			debug = 1;
1389f8bb9a5Skettenis 			break;
1399f8bb9a5Skettenis 		default:
1409f8bb9a5Skettenis 			usage();
1419f8bb9a5Skettenis 			/* NOTREACHED */
1429f8bb9a5Skettenis 		}
1439f8bb9a5Skettenis 	}
1449f8bb9a5Skettenis 
1459f8bb9a5Skettenis 	argc -= optind;
1469f8bb9a5Skettenis 	argv += optind;
1479f8bb9a5Skettenis 	if (argc > 0)
1489f8bb9a5Skettenis 		usage();
1499f8bb9a5Skettenis 
1509f8bb9a5Skettenis 	if (!debug)
1519f8bb9a5Skettenis 		if (daemon(0, 0))
1529f8bb9a5Skettenis 			fatal("daemon");
1539f8bb9a5Skettenis 
1549f8bb9a5Skettenis 	log_init(debug);
155df17ef41Skettenis 
156ee8d39aaSkettenis 	hv_open();
157df17ef41Skettenis 
158df17ef41Skettenis 	/*
159df17ef41Skettenis 	 * Request config.
160df17ef41Skettenis 	 */
161df17ef41Skettenis 	bzero(&msg, sizeof(msg));
162df17ef41Skettenis 	msg.hdr.op = HVCTL_OP_GET_HVCONFIG;
163df17ef41Skettenis 	msg.hdr.seq = hvctl_seq++;
164df17ef41Skettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
165df17ef41Skettenis 	if (nbytes != sizeof(msg))
1669f8bb9a5Skettenis 		fatal("write");
167df17ef41Skettenis 
168df17ef41Skettenis 	bzero(&msg, sizeof(msg));
169df17ef41Skettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
170df17ef41Skettenis 	if (nbytes != sizeof(msg))
1719f8bb9a5Skettenis 		fatal("read");
172df17ef41Skettenis 
173df17ef41Skettenis 	hv_mdpa = msg.msg.hvcnf.hvmdp;
1749f8bb9a5Skettenis 	hv_read(hv_mdpa, &hdr, sizeof(hdr));
175df17ef41Skettenis 	hvmd_len = sizeof(hdr) + hdr.node_blk_sz + hdr.name_blk_sz +
176df17ef41Skettenis 	    hdr.data_blk_sz;
177df17ef41Skettenis 	hvmd_buf = xmalloc(hvmd_len);
1789f8bb9a5Skettenis 	hv_read(hv_mdpa, hvmd_buf, hvmd_len);
179df17ef41Skettenis 
180df17ef41Skettenis 	hvmd = md_ingest(hvmd_buf, hvmd_len);
181df17ef41Skettenis 	node = md_find_node(hvmd, "guests");
182df17ef41Skettenis 	TAILQ_INIT(&guests);
183df17ef41Skettenis 	TAILQ_FOREACH(prop, &node->prop_list, link) {
184df17ef41Skettenis 		if (prop->tag == MD_PROP_ARC &&
185df17ef41Skettenis 		    strcmp(prop->name->str, "fwd") == 0)
186df17ef41Skettenis 			add_guest(prop->d.arc.node);
187df17ef41Skettenis 	}
188df17ef41Skettenis 
189df17ef41Skettenis 	frag_init();
190df17ef41Skettenis 
191be8be80fSkettenis 	TAILQ_FOREACH(guest, &guests, link) {
192be8be80fSkettenis 		struct ds_conn *dc;
193be8be80fSkettenis 		char path[64];
194df17ef41Skettenis 
195be8be80fSkettenis 		if (strcmp(guest->name, "primary") == 0)
196be8be80fSkettenis 			continue;
197df17ef41Skettenis 
198be8be80fSkettenis 		snprintf(path, sizeof(path), "/dev/ldom-%s", guest->name);
199be8be80fSkettenis 		dc = ds_conn_open(path, guest);
200be8be80fSkettenis 		ds_conn_register_service(dc, &var_config_service);
201df17ef41Skettenis 	}
202df17ef41Skettenis 
203ee8d39aaSkettenis 	hv_close();
204ee8d39aaSkettenis 
205be8be80fSkettenis 	ds_conn_serve();
206df17ef41Skettenis 
207df17ef41Skettenis 	exit(EXIT_SUCCESS);
208df17ef41Skettenis }
209df17ef41Skettenis 
210df17ef41Skettenis void
211df17ef41Skettenis usage(void)
212df17ef41Skettenis {
213df17ef41Skettenis 	extern char *__progname;
214df17ef41Skettenis 
2159f8bb9a5Skettenis 	fprintf(stderr, "usage: %s [-d]\n", __progname);
216df17ef41Skettenis 	exit(EXIT_FAILURE);
217df17ef41Skettenis }
218df17ef41Skettenis 
219df17ef41Skettenis void
220df17ef41Skettenis add_guest(struct md_node *node)
221df17ef41Skettenis {
222df17ef41Skettenis 	struct guest *guest;
223df17ef41Skettenis 	struct md_header hdr;
224df17ef41Skettenis 	void *buf;
225df17ef41Skettenis 	size_t len;
226df17ef41Skettenis 
227df17ef41Skettenis 	guest = xmalloc(sizeof(*guest));
228df17ef41Skettenis 
229df17ef41Skettenis 	if (!md_get_prop_str(hvmd, node, "name", &guest->name))
230df17ef41Skettenis 		goto free;
231df17ef41Skettenis 	if (!md_get_prop_val(hvmd, node, "gid", &guest->gid))
232df17ef41Skettenis 		goto free;
233df17ef41Skettenis 	if (!md_get_prop_val(hvmd, node, "mdpa", &guest->mdpa))
234df17ef41Skettenis 		goto free;
235df17ef41Skettenis 
2369f8bb9a5Skettenis 	hv_read(guest->mdpa, &hdr, sizeof(hdr));
237df17ef41Skettenis 	len = sizeof(hdr) + hdr.node_blk_sz + hdr.name_blk_sz +
238df17ef41Skettenis 	    hdr.data_blk_sz;
239df17ef41Skettenis 	buf = xmalloc(len);
2409f8bb9a5Skettenis 	hv_read(guest->mdpa, buf, len);
241df17ef41Skettenis 
242df17ef41Skettenis 	guest->node = node;
243df17ef41Skettenis 	guest->md = md_ingest(buf, len);
244be8be80fSkettenis 	if (strcmp(guest->name, "primary") == 0)
245be8be80fSkettenis 		map_domain_services(guest->md);
246df17ef41Skettenis 
247df17ef41Skettenis 	TAILQ_INSERT_TAIL(&guests, guest, link);
248be8be80fSkettenis 	return;
249be8be80fSkettenis 
250df17ef41Skettenis free:
251df17ef41Skettenis 	free(guest);
252df17ef41Skettenis }
253df17ef41Skettenis 
254be8be80fSkettenis void
255be8be80fSkettenis map_domain_services(struct md *md)
256be8be80fSkettenis {
257be8be80fSkettenis 	struct md_node *node;
258be8be80fSkettenis 	const char *name;
259be8be80fSkettenis 	char source[64];
260be8be80fSkettenis 	char target[64];
261be8be80fSkettenis 	int unit = 0;
262be8be80fSkettenis 
263be8be80fSkettenis 	TAILQ_FOREACH(node, &md->node_list, link) {
264be8be80fSkettenis 		if (strcmp(node->name->str, "virtual-device-port") != 0)
265be8be80fSkettenis 			continue;
266be8be80fSkettenis 
267be8be80fSkettenis 		if (!md_get_prop_str(md, node, "vldc-svc-name", &name))
268be8be80fSkettenis 			continue;
269be8be80fSkettenis 
270be8be80fSkettenis 		if (strncmp(name, "ldom-", 5) != 0 ||
271be8be80fSkettenis 		    strcmp(name, "ldom-primary") == 0)
272be8be80fSkettenis 			continue;
273be8be80fSkettenis 
274be8be80fSkettenis 		snprintf(source, sizeof(source), "/dev/ldom%d", unit++);
275be8be80fSkettenis 		snprintf(target, sizeof(target), "/dev/%s", name);
276be8be80fSkettenis 		unlink(target);
277be8be80fSkettenis 		symlink(source, target);
278be8be80fSkettenis 	}
279be8be80fSkettenis }
280df17ef41Skettenis 
281df17ef41Skettenis struct frag {
282df17ef41Skettenis 	TAILQ_ENTRY(frag) link;
283df17ef41Skettenis 	uint64_t base;
284df17ef41Skettenis };
285df17ef41Skettenis 
286df17ef41Skettenis TAILQ_HEAD(frag_head, frag) free_frags;
287df17ef41Skettenis 
288df17ef41Skettenis uint64_t fragsize;
289df17ef41Skettenis 
290df17ef41Skettenis void
291df17ef41Skettenis frag_init(void)
292df17ef41Skettenis {
293df17ef41Skettenis 	struct md_node *node;
294df17ef41Skettenis 	struct md_prop *prop;
295df17ef41Skettenis 
296df17ef41Skettenis 	node = md_find_node(hvmd, "frag_space");
297df17ef41Skettenis 	md_get_prop_val(hvmd, node, "fragsize", &fragsize);
298df17ef41Skettenis 	TAILQ_INIT(&free_frags);
299df17ef41Skettenis 	TAILQ_FOREACH(prop, &node->prop_list, link) {
300df17ef41Skettenis 		if (prop->tag == MD_PROP_ARC &&
301df17ef41Skettenis 		    strcmp(prop->name->str, "fwd") == 0)
302df17ef41Skettenis 			add_frag_mblock(prop->d.arc.node);
303df17ef41Skettenis 	}
304df17ef41Skettenis }
305df17ef41Skettenis 
306df17ef41Skettenis void
307df17ef41Skettenis add_frag_mblock(struct md_node *node)
308df17ef41Skettenis {
309df17ef41Skettenis 	uint64_t base, size;
310df17ef41Skettenis 	struct guest *guest;
311df17ef41Skettenis 
312df17ef41Skettenis 	md_get_prop_val(hvmd, node, "base", &base);
313df17ef41Skettenis 	md_get_prop_val(hvmd, node, "size", &size);
314df17ef41Skettenis 	while (size > fragsize) {
315df17ef41Skettenis 		add_frag(base);
316df17ef41Skettenis 		size -= fragsize;
317df17ef41Skettenis 		base += fragsize;
318df17ef41Skettenis 	}
319df17ef41Skettenis 
320df17ef41Skettenis 	delete_frag(hv_mdpa);
321df17ef41Skettenis 	TAILQ_FOREACH(guest, &guests, link)
322df17ef41Skettenis 		delete_frag(guest->mdpa);
323df17ef41Skettenis }
324df17ef41Skettenis 
325df17ef41Skettenis void
326df17ef41Skettenis add_frag(uint64_t base)
327df17ef41Skettenis {
328df17ef41Skettenis 	struct frag *frag;
329df17ef41Skettenis 
330df17ef41Skettenis 	frag = xmalloc(sizeof(*frag));
331df17ef41Skettenis 	frag->base = base;
332df17ef41Skettenis 	TAILQ_INSERT_TAIL(&free_frags, frag, link);
333df17ef41Skettenis }
334df17ef41Skettenis 
335df17ef41Skettenis void
336df17ef41Skettenis delete_frag(uint64_t base)
337df17ef41Skettenis {
338df17ef41Skettenis 	struct frag *frag;
339df17ef41Skettenis 	struct frag *tmp;
340df17ef41Skettenis 
341df17ef41Skettenis 	TAILQ_FOREACH_SAFE(frag, &free_frags, link, tmp) {
342df17ef41Skettenis 		if (frag->base == base) {
343df17ef41Skettenis 			TAILQ_REMOVE(&free_frags, frag, link);
344df17ef41Skettenis 			free(frag);
345df17ef41Skettenis 		}
346df17ef41Skettenis 	}
347df17ef41Skettenis }
348df17ef41Skettenis 
349df17ef41Skettenis uint64_t
350df17ef41Skettenis alloc_frag(void)
351df17ef41Skettenis {
352df17ef41Skettenis 	struct frag *frag;
353df17ef41Skettenis 	uint64_t base;
354df17ef41Skettenis 
355df17ef41Skettenis 	frag = TAILQ_FIRST(&free_frags);
356df17ef41Skettenis 	if (frag == NULL)
357df17ef41Skettenis 		return -1;
358df17ef41Skettenis 
359df17ef41Skettenis 	TAILQ_REMOVE(&free_frags, frag, link);
360df17ef41Skettenis 	base = frag->base;
361df17ef41Skettenis 	free(frag);
362df17ef41Skettenis 
363df17ef41Skettenis 	return base;
364df17ef41Skettenis }
365df17ef41Skettenis 
366df17ef41Skettenis void
367df17ef41Skettenis hv_update_md(struct guest *guest)
368df17ef41Skettenis {
369df17ef41Skettenis 	struct hvctl_msg msg;
370df17ef41Skettenis 	size_t nbytes;
371df17ef41Skettenis 	void *buf;
372df17ef41Skettenis 	size_t size;
373be8be80fSkettenis 	uint64_t mdpa;
374df17ef41Skettenis 
375ee8d39aaSkettenis 	hv_open();
376ee8d39aaSkettenis 
377be8be80fSkettenis 	mdpa = alloc_frag();
378df17ef41Skettenis 	size = md_exhume(guest->md, &buf);
379be8be80fSkettenis 	hv_write(mdpa, buf, size);
380be8be80fSkettenis 	add_frag(guest->mdpa);
381be8be80fSkettenis 	guest->mdpa = mdpa;
382df17ef41Skettenis 	free(buf);
383df17ef41Skettenis 
384df17ef41Skettenis 	md_set_prop_val(hvmd, guest->node, "mdpa", guest->mdpa);
385df17ef41Skettenis 
386be8be80fSkettenis 	mdpa = alloc_frag();
387df17ef41Skettenis 	size = md_exhume(hvmd, &buf);
388be8be80fSkettenis 	hv_write(mdpa, buf, size);
389be8be80fSkettenis 	add_frag(hv_mdpa);
390be8be80fSkettenis 	hv_mdpa = mdpa;
391df17ef41Skettenis 	free(buf);
392df17ef41Skettenis 
393df17ef41Skettenis 	/* Update config.  */
394df17ef41Skettenis 	bzero(&msg, sizeof(msg));
395df17ef41Skettenis 	msg.hdr.op = HVCTL_OP_RECONFIGURE;
396df17ef41Skettenis 	msg.hdr.seq = hvctl_seq++;
397df17ef41Skettenis 	msg.msg.reconfig.guestid = -1;
398df17ef41Skettenis 	msg.msg.reconfig.hvmdp = hv_mdpa;
399df17ef41Skettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
400df17ef41Skettenis 	if (nbytes != sizeof(msg))
4019f8bb9a5Skettenis 		fatal("write");
402df17ef41Skettenis 
403df17ef41Skettenis 	bzero(&msg, sizeof(msg));
404df17ef41Skettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
405df17ef41Skettenis 	if (nbytes != sizeof(msg))
4069f8bb9a5Skettenis 		fatal("read");
4079f8bb9a5Skettenis 
408ee8d39aaSkettenis 	hv_close();
409ee8d39aaSkettenis 
4109f8bb9a5Skettenis 	if (msg.hdr.status != HVCTL_ST_OK)
4119f8bb9a5Skettenis 		logit(LOG_CRIT, "reconfigure failed: %d", msg.hdr.status);
4129f8bb9a5Skettenis }
4139f8bb9a5Skettenis 
4149f8bb9a5Skettenis void
415ee8d39aaSkettenis hv_open(void)
416ee8d39aaSkettenis {
417ee8d39aaSkettenis 	struct hvctl_msg msg;
418ee8d39aaSkettenis 	ssize_t nbytes;
419ee8d39aaSkettenis 	uint64_t code;
420ee8d39aaSkettenis 
421ee8d39aaSkettenis 	hvctl_fd = open("/dev/hvctl", O_RDWR, 0);
422ee8d39aaSkettenis 	if (hvctl_fd == -1)
423ee8d39aaSkettenis 		fatal("cannot open /dev/hvctl");
424ee8d39aaSkettenis 
425ee8d39aaSkettenis 	/*
426ee8d39aaSkettenis 	 * Say "Hello".
427ee8d39aaSkettenis 	 */
428ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
429ee8d39aaSkettenis 	msg.hdr.op = HVCTL_OP_HELLO;
430ee8d39aaSkettenis 	msg.hdr.seq = hvctl_seq++;
431ee8d39aaSkettenis 	msg.msg.hello.major = 1;
432ee8d39aaSkettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
433ee8d39aaSkettenis 	if (nbytes != sizeof(msg))
434ee8d39aaSkettenis 		fatal("write");
435ee8d39aaSkettenis 
436ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
437ee8d39aaSkettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
438ee8d39aaSkettenis 	if (nbytes != sizeof(msg))
439ee8d39aaSkettenis 		fatal("read");
440ee8d39aaSkettenis 
441ee8d39aaSkettenis 	code = msg.msg.clnge.code ^ 0xbadbeef20;
442ee8d39aaSkettenis 
443ee8d39aaSkettenis 	/*
444ee8d39aaSkettenis 	 * Respond to challenge.
445ee8d39aaSkettenis 	 */
446ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
447ee8d39aaSkettenis 	msg.hdr.op = HVCTL_OP_RESPONSE;
448ee8d39aaSkettenis 	msg.hdr.seq = hvctl_seq++;
449ee8d39aaSkettenis 	msg.msg.clnge.code = code ^ 0x12cafe42a;
450ee8d39aaSkettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
451ee8d39aaSkettenis 	if (nbytes != sizeof(msg))
452ee8d39aaSkettenis 		fatal("write");
453ee8d39aaSkettenis 
454ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
455ee8d39aaSkettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
456ee8d39aaSkettenis 	if (nbytes != sizeof(msg))
457ee8d39aaSkettenis 		fatal("read");
458ee8d39aaSkettenis }
459ee8d39aaSkettenis 
460ee8d39aaSkettenis void
461ee8d39aaSkettenis hv_close(void)
462ee8d39aaSkettenis {
463ee8d39aaSkettenis 	close(hvctl_fd);
464ee8d39aaSkettenis 	hvctl_fd = -1;
465ee8d39aaSkettenis }
466ee8d39aaSkettenis 
467ee8d39aaSkettenis void
4689f8bb9a5Skettenis hv_read(uint64_t addr, void *buf, size_t len)
4699f8bb9a5Skettenis {
4709f8bb9a5Skettenis 	struct hv_io hi;
4719f8bb9a5Skettenis 
4729f8bb9a5Skettenis 	hi.hi_cookie = addr;
4739f8bb9a5Skettenis 	hi.hi_addr = buf;
4749f8bb9a5Skettenis 	hi.hi_len = len;
4759f8bb9a5Skettenis 
4769f8bb9a5Skettenis 	if (ioctl(hvctl_fd, HVIOCREAD, &hi) == -1)
4779f8bb9a5Skettenis 		fatal("ioctl");
478df17ef41Skettenis }
479df17ef41Skettenis 
480df17ef41Skettenis void
481df17ef41Skettenis hv_write(uint64_t addr, void *buf, size_t len)
482df17ef41Skettenis {
483df17ef41Skettenis 	struct hv_io hi;
484df17ef41Skettenis 
485df17ef41Skettenis 	hi.hi_cookie = addr;
486df17ef41Skettenis 	hi.hi_addr = buf;
487df17ef41Skettenis 	hi.hi_len = len;
488df17ef41Skettenis 
489df17ef41Skettenis 	if (ioctl(hvctl_fd, HVIOCWRITE, &hi) == -1)
4909f8bb9a5Skettenis 		fatal("ioctl");
491df17ef41Skettenis }
492