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