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