xref: /openbsd/usr.sbin/ldomd/ldomd.c (revision b7041c07)
1*b7041c07Sderaadt /*	$OpenBSD: ldomd.c,v 1.11 2021/10/24 21:24:18 deraadt 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>
28ce902648Sderaadt #include <limits.h>
29df17ef41Skettenis #include <string.h>
309f8bb9a5Skettenis #include <syslog.h>
312e71478cSguenther #include <time.h>
32df17ef41Skettenis #include <unistd.h>
33df17ef41Skettenis 
34df17ef41Skettenis #include "ds.h"
3534574250Skettenis #include "hvctl.h"
36df17ef41Skettenis #include "mdesc.h"
37d73a4c4fSkn #include "ldom_util.h"
38be8be80fSkettenis #include "ldomd.h"
39df17ef41Skettenis 
40df17ef41Skettenis TAILQ_HEAD(guest_head, guest) guests;
41df17ef41Skettenis 
42df17ef41Skettenis void add_guest(struct md_node *);
43be8be80fSkettenis void map_domain_services(struct md *);
44df17ef41Skettenis 
45df17ef41Skettenis void frag_init(void);
46df17ef41Skettenis void add_frag_mblock(struct md_node *);
47df17ef41Skettenis void add_frag(uint64_t);
48df17ef41Skettenis void delete_frag(uint64_t);
49df17ef41Skettenis uint64_t alloc_frag(void);
50df17ef41Skettenis 
51df17ef41Skettenis void hv_update_md(struct guest *guest);
52ee8d39aaSkettenis void hv_open(void);
53ee8d39aaSkettenis void hv_close(void);
549f8bb9a5Skettenis void hv_read(uint64_t, void *, size_t);
55df17ef41Skettenis void hv_write(uint64_t, void *, size_t);
56df17ef41Skettenis 
57df17ef41Skettenis int hvctl_seq = 1;
58df17ef41Skettenis int hvctl_fd;
59df17ef41Skettenis 
60df17ef41Skettenis void *hvmd_buf;
61df17ef41Skettenis size_t hvmd_len;
62df17ef41Skettenis struct md *hvmd;
63df17ef41Skettenis uint64_t hv_mdpa;
64df17ef41Skettenis 
659f8bb9a5Skettenis __dead void	usage(void);
669f8bb9a5Skettenis void	logit(int, const char *, ...);
679f8bb9a5Skettenis void	vlog(int, const char *, va_list);
689f8bb9a5Skettenis 
699f8bb9a5Skettenis void
log_init(int n_debug)709f8bb9a5Skettenis log_init(int n_debug)
719f8bb9a5Skettenis {
729f8bb9a5Skettenis 	extern char *__progname;
739f8bb9a5Skettenis 
749f8bb9a5Skettenis 	debug = n_debug;
759f8bb9a5Skettenis 
769f8bb9a5Skettenis 	if (!debug)
779f8bb9a5Skettenis 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
789f8bb9a5Skettenis 
799f8bb9a5Skettenis 	tzset();
809f8bb9a5Skettenis }
819f8bb9a5Skettenis 
829f8bb9a5Skettenis void
fatal(const char * emsg)839f8bb9a5Skettenis fatal(const char *emsg)
849f8bb9a5Skettenis {
859f8bb9a5Skettenis 	if (errno)
869f8bb9a5Skettenis 		logit(LOG_CRIT, "fatal: %s: %s\n", emsg, strerror(errno));
879f8bb9a5Skettenis 	else
889f8bb9a5Skettenis 		logit(LOG_CRIT, "fatal: %s\n", emsg);
899f8bb9a5Skettenis 
909f8bb9a5Skettenis 	exit(EXIT_FAILURE);
919f8bb9a5Skettenis }
929f8bb9a5Skettenis 
939f8bb9a5Skettenis void
logit(int pri,const char * fmt,...)949f8bb9a5Skettenis logit(int pri, const char *fmt, ...)
959f8bb9a5Skettenis {
969f8bb9a5Skettenis 	va_list ap;
979f8bb9a5Skettenis 
989f8bb9a5Skettenis 	va_start(ap, fmt);
999f8bb9a5Skettenis 	vlog(pri, fmt, ap);
1009f8bb9a5Skettenis 	va_end(ap);
1019f8bb9a5Skettenis }
1029f8bb9a5Skettenis 
1039f8bb9a5Skettenis void
vlog(int pri,const char * fmt,va_list ap)1049f8bb9a5Skettenis vlog(int pri, const char *fmt, va_list ap)
1059f8bb9a5Skettenis {
1069f8bb9a5Skettenis 	char *nfmt;
1079f8bb9a5Skettenis 
1089f8bb9a5Skettenis 	if (debug) {
1099f8bb9a5Skettenis 		/* best effort in out of mem situations */
1109f8bb9a5Skettenis 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
1119f8bb9a5Skettenis 			vfprintf(stderr, fmt, ap);
1129f8bb9a5Skettenis 			fprintf(stderr, "\n");
1139f8bb9a5Skettenis 		} else {
1149f8bb9a5Skettenis 			vfprintf(stderr, nfmt, ap);
1159f8bb9a5Skettenis 			free(nfmt);
1169f8bb9a5Skettenis 		}
1179f8bb9a5Skettenis 		fflush(stderr);
1189f8bb9a5Skettenis 	} else
1199f8bb9a5Skettenis 		vsyslog(pri, fmt, ap);
1209f8bb9a5Skettenis }
1219f8bb9a5Skettenis 
122df17ef41Skettenis int
main(int argc,char ** argv)123df17ef41Skettenis main(int argc, char **argv)
124df17ef41Skettenis {
125df17ef41Skettenis 	struct hvctl_msg msg;
126df17ef41Skettenis 	ssize_t nbytes;
127df17ef41Skettenis 	struct md_header hdr;
128df17ef41Skettenis 	struct md_node *node;
129df17ef41Skettenis 	struct md_prop *prop;
130be8be80fSkettenis 	struct guest *guest;
1319f8bb9a5Skettenis 	int debug = 0;
1329f8bb9a5Skettenis 	int ch;
13346169cb9Skettenis 	int i;
1349f8bb9a5Skettenis 
1359f8bb9a5Skettenis 	log_init(1);
1369f8bb9a5Skettenis 
1379f8bb9a5Skettenis 	while ((ch = getopt(argc, argv, "d")) != -1) {
1389f8bb9a5Skettenis 		switch (ch) {
1399f8bb9a5Skettenis 		case 'd':
1409f8bb9a5Skettenis 			debug = 1;
1419f8bb9a5Skettenis 			break;
1429f8bb9a5Skettenis 		default:
1439f8bb9a5Skettenis 			usage();
1449f8bb9a5Skettenis 			/* NOTREACHED */
1459f8bb9a5Skettenis 		}
1469f8bb9a5Skettenis 	}
1479f8bb9a5Skettenis 
1489f8bb9a5Skettenis 	argc -= optind;
1499f8bb9a5Skettenis 	argv += optind;
1509f8bb9a5Skettenis 	if (argc > 0)
1519f8bb9a5Skettenis 		usage();
1529f8bb9a5Skettenis 
1539f8bb9a5Skettenis 	if (!debug)
1549f8bb9a5Skettenis 		if (daemon(0, 0))
1559f8bb9a5Skettenis 			fatal("daemon");
1569f8bb9a5Skettenis 
1579f8bb9a5Skettenis 	log_init(debug);
158df17ef41Skettenis 
159ee8d39aaSkettenis 	hv_open();
160df17ef41Skettenis 
161df17ef41Skettenis 	/*
162df17ef41Skettenis 	 * Request config.
163df17ef41Skettenis 	 */
164df17ef41Skettenis 	bzero(&msg, sizeof(msg));
165df17ef41Skettenis 	msg.hdr.op = HVCTL_OP_GET_HVCONFIG;
166df17ef41Skettenis 	msg.hdr.seq = hvctl_seq++;
167df17ef41Skettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
168df17ef41Skettenis 	if (nbytes != sizeof(msg))
1699f8bb9a5Skettenis 		fatal("write");
170df17ef41Skettenis 
171df17ef41Skettenis 	bzero(&msg, sizeof(msg));
172df17ef41Skettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
173df17ef41Skettenis 	if (nbytes != sizeof(msg))
1749f8bb9a5Skettenis 		fatal("read");
175df17ef41Skettenis 
176df17ef41Skettenis 	hv_mdpa = msg.msg.hvcnf.hvmdp;
1779f8bb9a5Skettenis 	hv_read(hv_mdpa, &hdr, sizeof(hdr));
178df17ef41Skettenis 	hvmd_len = sizeof(hdr) + hdr.node_blk_sz + hdr.name_blk_sz +
179df17ef41Skettenis 	    hdr.data_blk_sz;
180df17ef41Skettenis 	hvmd_buf = xmalloc(hvmd_len);
1819f8bb9a5Skettenis 	hv_read(hv_mdpa, hvmd_buf, hvmd_len);
182df17ef41Skettenis 
183df17ef41Skettenis 	hvmd = md_ingest(hvmd_buf, hvmd_len);
184df17ef41Skettenis 	node = md_find_node(hvmd, "guests");
185df17ef41Skettenis 	TAILQ_INIT(&guests);
186df17ef41Skettenis 	TAILQ_FOREACH(prop, &node->prop_list, link) {
187df17ef41Skettenis 		if (prop->tag == MD_PROP_ARC &&
188df17ef41Skettenis 		    strcmp(prop->name->str, "fwd") == 0)
189df17ef41Skettenis 			add_guest(prop->d.arc.node);
190df17ef41Skettenis 	}
191df17ef41Skettenis 
192df17ef41Skettenis 	frag_init();
193df17ef41Skettenis 
194be8be80fSkettenis 	TAILQ_FOREACH(guest, &guests, link) {
195be8be80fSkettenis 		struct ds_conn *dc;
196dc01f726Sderaadt 		char path[PATH_MAX];
197df17ef41Skettenis 
198be8be80fSkettenis 		if (strcmp(guest->name, "primary") == 0)
199be8be80fSkettenis 			continue;
200df17ef41Skettenis 
201be8be80fSkettenis 		snprintf(path, sizeof(path), "/dev/ldom-%s", guest->name);
202be8be80fSkettenis 		dc = ds_conn_open(path, guest);
203be8be80fSkettenis 		ds_conn_register_service(dc, &var_config_service);
204df17ef41Skettenis 	}
205df17ef41Skettenis 
206ee8d39aaSkettenis 	hv_close();
207ee8d39aaSkettenis 
20846169cb9Skettenis 	/*
20946169cb9Skettenis 	 * Open all virtual disk server port device files.  As long as
21046169cb9Skettenis 	 * we keep these device files open, the corresponding virtual
21146169cb9Skettenis 	 * disks will be available to the guest domains.  For now we
21246169cb9Skettenis 	 * just keep them open until we exit, so there is not reason
21346169cb9Skettenis 	 * to keep track of the file descriptors.
21446169cb9Skettenis 	 */
21546169cb9Skettenis 	for (i = 0; i < 256; i++) {
216dc01f726Sderaadt 		char path[PATH_MAX];
21746169cb9Skettenis 
21846169cb9Skettenis 		snprintf(path, sizeof(path), "/dev/vdsp%d", i);
219*b7041c07Sderaadt 		if (open(path, O_RDWR) == -1)
22046169cb9Skettenis 			break;
22146169cb9Skettenis 	}
22246169cb9Skettenis 
223be8be80fSkettenis 	ds_conn_serve();
224df17ef41Skettenis 
225df17ef41Skettenis 	exit(EXIT_SUCCESS);
226df17ef41Skettenis }
227df17ef41Skettenis 
228df17ef41Skettenis void
usage(void)229df17ef41Skettenis usage(void)
230df17ef41Skettenis {
231df17ef41Skettenis 	extern char *__progname;
232df17ef41Skettenis 
2339f8bb9a5Skettenis 	fprintf(stderr, "usage: %s [-d]\n", __progname);
234df17ef41Skettenis 	exit(EXIT_FAILURE);
235df17ef41Skettenis }
236df17ef41Skettenis 
237df17ef41Skettenis void
add_guest(struct md_node * node)238df17ef41Skettenis add_guest(struct md_node *node)
239df17ef41Skettenis {
240df17ef41Skettenis 	struct guest *guest;
241df17ef41Skettenis 	struct md_header hdr;
242df17ef41Skettenis 	void *buf;
243df17ef41Skettenis 	size_t len;
244df17ef41Skettenis 
245df17ef41Skettenis 	guest = xmalloc(sizeof(*guest));
246df17ef41Skettenis 
247df17ef41Skettenis 	if (!md_get_prop_str(hvmd, node, "name", &guest->name))
248df17ef41Skettenis 		goto free;
249df17ef41Skettenis 	if (!md_get_prop_val(hvmd, node, "gid", &guest->gid))
250df17ef41Skettenis 		goto free;
251df17ef41Skettenis 	if (!md_get_prop_val(hvmd, node, "mdpa", &guest->mdpa))
252df17ef41Skettenis 		goto free;
253df17ef41Skettenis 
2549f8bb9a5Skettenis 	hv_read(guest->mdpa, &hdr, sizeof(hdr));
255df17ef41Skettenis 	len = sizeof(hdr) + hdr.node_blk_sz + hdr.name_blk_sz +
256df17ef41Skettenis 	    hdr.data_blk_sz;
257df17ef41Skettenis 	buf = xmalloc(len);
2589f8bb9a5Skettenis 	hv_read(guest->mdpa, buf, len);
259df17ef41Skettenis 
260df17ef41Skettenis 	guest->node = node;
261df17ef41Skettenis 	guest->md = md_ingest(buf, len);
262be8be80fSkettenis 	if (strcmp(guest->name, "primary") == 0)
263be8be80fSkettenis 		map_domain_services(guest->md);
264df17ef41Skettenis 
265df17ef41Skettenis 	TAILQ_INSERT_TAIL(&guests, guest, link);
266be8be80fSkettenis 	return;
267be8be80fSkettenis 
268df17ef41Skettenis free:
269df17ef41Skettenis 	free(guest);
270df17ef41Skettenis }
271df17ef41Skettenis 
272be8be80fSkettenis void
map_domain_services(struct md * md)273be8be80fSkettenis map_domain_services(struct md *md)
274be8be80fSkettenis {
275be8be80fSkettenis 	struct md_node *node;
276be8be80fSkettenis 	const char *name;
277be8be80fSkettenis 	char source[64];
278be8be80fSkettenis 	char target[64];
279be8be80fSkettenis 	int unit = 0;
280be8be80fSkettenis 
281be8be80fSkettenis 	TAILQ_FOREACH(node, &md->node_list, link) {
282be8be80fSkettenis 		if (strcmp(node->name->str, "virtual-device-port") != 0)
283be8be80fSkettenis 			continue;
284be8be80fSkettenis 
285be8be80fSkettenis 		if (!md_get_prop_str(md, node, "vldc-svc-name", &name))
286be8be80fSkettenis 			continue;
287be8be80fSkettenis 
288be8be80fSkettenis 		if (strncmp(name, "ldom-", 5) != 0 ||
289be8be80fSkettenis 		    strcmp(name, "ldom-primary") == 0)
290be8be80fSkettenis 			continue;
291be8be80fSkettenis 
292be8be80fSkettenis 		snprintf(source, sizeof(source), "/dev/ldom%d", unit++);
293be8be80fSkettenis 		snprintf(target, sizeof(target), "/dev/%s", name);
294be8be80fSkettenis 		unlink(target);
295be8be80fSkettenis 		symlink(source, target);
296be8be80fSkettenis 	}
297be8be80fSkettenis }
298df17ef41Skettenis 
299df17ef41Skettenis struct frag {
300df17ef41Skettenis 	TAILQ_ENTRY(frag) link;
301df17ef41Skettenis 	uint64_t base;
302df17ef41Skettenis };
303df17ef41Skettenis 
304df17ef41Skettenis TAILQ_HEAD(frag_head, frag) free_frags;
305df17ef41Skettenis 
306df17ef41Skettenis uint64_t fragsize;
307df17ef41Skettenis 
308df17ef41Skettenis void
frag_init(void)309df17ef41Skettenis frag_init(void)
310df17ef41Skettenis {
311df17ef41Skettenis 	struct md_node *node;
312df17ef41Skettenis 	struct md_prop *prop;
313df17ef41Skettenis 
314df17ef41Skettenis 	node = md_find_node(hvmd, "frag_space");
315df17ef41Skettenis 	md_get_prop_val(hvmd, node, "fragsize", &fragsize);
316df17ef41Skettenis 	TAILQ_INIT(&free_frags);
317df17ef41Skettenis 	TAILQ_FOREACH(prop, &node->prop_list, link) {
318df17ef41Skettenis 		if (prop->tag == MD_PROP_ARC &&
319df17ef41Skettenis 		    strcmp(prop->name->str, "fwd") == 0)
320df17ef41Skettenis 			add_frag_mblock(prop->d.arc.node);
321df17ef41Skettenis 	}
322df17ef41Skettenis }
323df17ef41Skettenis 
324df17ef41Skettenis void
add_frag_mblock(struct md_node * node)325df17ef41Skettenis add_frag_mblock(struct md_node *node)
326df17ef41Skettenis {
327df17ef41Skettenis 	uint64_t base, size;
328df17ef41Skettenis 	struct guest *guest;
329df17ef41Skettenis 
330df17ef41Skettenis 	md_get_prop_val(hvmd, node, "base", &base);
331df17ef41Skettenis 	md_get_prop_val(hvmd, node, "size", &size);
332df17ef41Skettenis 	while (size > fragsize) {
333df17ef41Skettenis 		add_frag(base);
334df17ef41Skettenis 		size -= fragsize;
335df17ef41Skettenis 		base += fragsize;
336df17ef41Skettenis 	}
337df17ef41Skettenis 
338df17ef41Skettenis 	delete_frag(hv_mdpa);
339df17ef41Skettenis 	TAILQ_FOREACH(guest, &guests, link)
340df17ef41Skettenis 		delete_frag(guest->mdpa);
341df17ef41Skettenis }
342df17ef41Skettenis 
343df17ef41Skettenis void
add_frag(uint64_t base)344df17ef41Skettenis add_frag(uint64_t base)
345df17ef41Skettenis {
346df17ef41Skettenis 	struct frag *frag;
347df17ef41Skettenis 
348df17ef41Skettenis 	frag = xmalloc(sizeof(*frag));
349df17ef41Skettenis 	frag->base = base;
350df17ef41Skettenis 	TAILQ_INSERT_TAIL(&free_frags, frag, link);
351df17ef41Skettenis }
352df17ef41Skettenis 
353df17ef41Skettenis void
delete_frag(uint64_t base)354df17ef41Skettenis delete_frag(uint64_t base)
355df17ef41Skettenis {
356df17ef41Skettenis 	struct frag *frag;
357df17ef41Skettenis 	struct frag *tmp;
358df17ef41Skettenis 
359df17ef41Skettenis 	TAILQ_FOREACH_SAFE(frag, &free_frags, link, tmp) {
360df17ef41Skettenis 		if (frag->base == base) {
361df17ef41Skettenis 			TAILQ_REMOVE(&free_frags, frag, link);
362df17ef41Skettenis 			free(frag);
363df17ef41Skettenis 		}
364df17ef41Skettenis 	}
365df17ef41Skettenis }
366df17ef41Skettenis 
367df17ef41Skettenis uint64_t
alloc_frag(void)368df17ef41Skettenis alloc_frag(void)
369df17ef41Skettenis {
370df17ef41Skettenis 	struct frag *frag;
371df17ef41Skettenis 	uint64_t base;
372df17ef41Skettenis 
373df17ef41Skettenis 	frag = TAILQ_FIRST(&free_frags);
374df17ef41Skettenis 	if (frag == NULL)
375df17ef41Skettenis 		return -1;
376df17ef41Skettenis 
377df17ef41Skettenis 	TAILQ_REMOVE(&free_frags, frag, link);
378df17ef41Skettenis 	base = frag->base;
379df17ef41Skettenis 	free(frag);
380df17ef41Skettenis 
381df17ef41Skettenis 	return base;
382df17ef41Skettenis }
383df17ef41Skettenis 
384df17ef41Skettenis void
hv_update_md(struct guest * guest)385df17ef41Skettenis hv_update_md(struct guest *guest)
386df17ef41Skettenis {
387df17ef41Skettenis 	struct hvctl_msg msg;
388df17ef41Skettenis 	size_t nbytes;
389df17ef41Skettenis 	void *buf;
390df17ef41Skettenis 	size_t size;
391be8be80fSkettenis 	uint64_t mdpa;
392df17ef41Skettenis 
393ee8d39aaSkettenis 	hv_open();
394ee8d39aaSkettenis 
395be8be80fSkettenis 	mdpa = alloc_frag();
396df17ef41Skettenis 	size = md_exhume(guest->md, &buf);
397be8be80fSkettenis 	hv_write(mdpa, buf, size);
398be8be80fSkettenis 	add_frag(guest->mdpa);
399be8be80fSkettenis 	guest->mdpa = mdpa;
400df17ef41Skettenis 	free(buf);
401df17ef41Skettenis 
402df17ef41Skettenis 	md_set_prop_val(hvmd, guest->node, "mdpa", guest->mdpa);
403df17ef41Skettenis 
404be8be80fSkettenis 	mdpa = alloc_frag();
405df17ef41Skettenis 	size = md_exhume(hvmd, &buf);
406be8be80fSkettenis 	hv_write(mdpa, buf, size);
407be8be80fSkettenis 	add_frag(hv_mdpa);
408be8be80fSkettenis 	hv_mdpa = mdpa;
409df17ef41Skettenis 	free(buf);
410df17ef41Skettenis 
411df17ef41Skettenis 	/* Update config.  */
412df17ef41Skettenis 	bzero(&msg, sizeof(msg));
413df17ef41Skettenis 	msg.hdr.op = HVCTL_OP_RECONFIGURE;
414df17ef41Skettenis 	msg.hdr.seq = hvctl_seq++;
415df17ef41Skettenis 	msg.msg.reconfig.guestid = -1;
416df17ef41Skettenis 	msg.msg.reconfig.hvmdp = hv_mdpa;
417df17ef41Skettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
418df17ef41Skettenis 	if (nbytes != sizeof(msg))
4199f8bb9a5Skettenis 		fatal("write");
420df17ef41Skettenis 
421df17ef41Skettenis 	bzero(&msg, sizeof(msg));
422df17ef41Skettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
423df17ef41Skettenis 	if (nbytes != sizeof(msg))
4249f8bb9a5Skettenis 		fatal("read");
4259f8bb9a5Skettenis 
426ee8d39aaSkettenis 	hv_close();
427ee8d39aaSkettenis 
4289f8bb9a5Skettenis 	if (msg.hdr.status != HVCTL_ST_OK)
4299f8bb9a5Skettenis 		logit(LOG_CRIT, "reconfigure failed: %d", msg.hdr.status);
4309f8bb9a5Skettenis }
4319f8bb9a5Skettenis 
4329f8bb9a5Skettenis void
hv_open(void)433ee8d39aaSkettenis hv_open(void)
434ee8d39aaSkettenis {
435ee8d39aaSkettenis 	struct hvctl_msg msg;
436ee8d39aaSkettenis 	ssize_t nbytes;
437ee8d39aaSkettenis 	uint64_t code;
438ee8d39aaSkettenis 
439*b7041c07Sderaadt 	hvctl_fd = open("/dev/hvctl", O_RDWR);
440ee8d39aaSkettenis 	if (hvctl_fd == -1)
441ee8d39aaSkettenis 		fatal("cannot open /dev/hvctl");
442ee8d39aaSkettenis 
443ee8d39aaSkettenis 	/*
444ee8d39aaSkettenis 	 * Say "Hello".
445ee8d39aaSkettenis 	 */
446ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
447ee8d39aaSkettenis 	msg.hdr.op = HVCTL_OP_HELLO;
448ee8d39aaSkettenis 	msg.hdr.seq = hvctl_seq++;
449ee8d39aaSkettenis 	msg.msg.hello.major = 1;
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 	code = msg.msg.clnge.code ^ 0xbadbeef20;
460ee8d39aaSkettenis 
461ee8d39aaSkettenis 	/*
462ee8d39aaSkettenis 	 * Respond to challenge.
463ee8d39aaSkettenis 	 */
464ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
465ee8d39aaSkettenis 	msg.hdr.op = HVCTL_OP_RESPONSE;
466ee8d39aaSkettenis 	msg.hdr.seq = hvctl_seq++;
467ee8d39aaSkettenis 	msg.msg.clnge.code = code ^ 0x12cafe42a;
468ee8d39aaSkettenis 	nbytes = write(hvctl_fd, &msg, sizeof(msg));
469ee8d39aaSkettenis 	if (nbytes != sizeof(msg))
470ee8d39aaSkettenis 		fatal("write");
471ee8d39aaSkettenis 
472ee8d39aaSkettenis 	bzero(&msg, sizeof(msg));
473ee8d39aaSkettenis 	nbytes = read(hvctl_fd, &msg, sizeof(msg));
474ee8d39aaSkettenis 	if (nbytes != sizeof(msg))
475ee8d39aaSkettenis 		fatal("read");
476ee8d39aaSkettenis }
477ee8d39aaSkettenis 
478ee8d39aaSkettenis void
hv_close(void)479ee8d39aaSkettenis hv_close(void)
480ee8d39aaSkettenis {
481ee8d39aaSkettenis 	close(hvctl_fd);
482ee8d39aaSkettenis 	hvctl_fd = -1;
483ee8d39aaSkettenis }
484ee8d39aaSkettenis 
485ee8d39aaSkettenis void
hv_read(uint64_t addr,void * buf,size_t len)4869f8bb9a5Skettenis hv_read(uint64_t addr, void *buf, size_t len)
4879f8bb9a5Skettenis {
4889f8bb9a5Skettenis 	struct hv_io hi;
4899f8bb9a5Skettenis 
4909f8bb9a5Skettenis 	hi.hi_cookie = addr;
4919f8bb9a5Skettenis 	hi.hi_addr = buf;
4929f8bb9a5Skettenis 	hi.hi_len = len;
4939f8bb9a5Skettenis 
4949f8bb9a5Skettenis 	if (ioctl(hvctl_fd, HVIOCREAD, &hi) == -1)
4959f8bb9a5Skettenis 		fatal("ioctl");
496df17ef41Skettenis }
497df17ef41Skettenis 
498df17ef41Skettenis void
hv_write(uint64_t addr,void * buf,size_t len)499df17ef41Skettenis hv_write(uint64_t addr, void *buf, size_t len)
500df17ef41Skettenis {
501df17ef41Skettenis 	struct hv_io hi;
502df17ef41Skettenis 
503df17ef41Skettenis 	hi.hi_cookie = addr;
504df17ef41Skettenis 	hi.hi_addr = buf;
505df17ef41Skettenis 	hi.hi_len = len;
506df17ef41Skettenis 
507df17ef41Skettenis 	if (ioctl(hvctl_fd, HVIOCWRITE, &hi) == -1)
5089f8bb9a5Skettenis 		fatal("ioctl");
509df17ef41Skettenis }
510