From 155d1eca37c9f7e3c6328bd25836f6618a78bfa3 Mon Sep 17 00:00:00 2001 From: Kimihiro Nonaka Date: Fri, 23 Mar 2018 20:00:29 +0900 Subject: [PATCH 2/5] Hyper-V SynIC (WIP) --- sys/arch/amd64/conf/GENERIC | 3 + sys/arch/x86/conf/files.x86 | 10 +- sys/arch/x86/x86/hvheartbeat.c | 199 +++++++++++++++++++++ sys/arch/x86/x86/hvshutdown.c | 234 ++++++++++++++++++++++++ sys/arch/x86/x86/hvtimesync.c | 316 +++++++++++++++++++++++++++++++++ sys/arch/x86/x86/vmbusic.c | 272 ++++++++++++++++++++++++++++ sys/arch/x86/x86/vmbusicreg.h | 248 ++++++++++++++++++++++++++ sys/arch/x86/x86/vmbusicvar.h | 70 ++++++++ 8 files changed, 1347 insertions(+), 5 deletions(-) create mode 100644 sys/arch/x86/x86/hvheartbeat.c create mode 100644 sys/arch/x86/x86/hvshutdown.c create mode 100644 sys/arch/x86/x86/hvtimesync.c create mode 100644 sys/arch/x86/x86/vmbusic.c create mode 100644 sys/arch/x86/x86/vmbusicreg.h create mode 100644 sys/arch/x86/x86/vmbusicvar.h diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index 4272ae800aa..7a877e335b9 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1252,6 +1252,9 @@ vioscsi* at virtio? # Virtio SCSI device vmbus* at acpi? # Hyper-V VMBus #hvn* at vmbus? # Hyper-V NetVSC #hvs* at vmbus? # Hyper-V StorVSC +hvheartbeat* at vmbus? # Hyper-V Heartbeat +hvshutdown* at vmbus? # Hyper-V Shutdown +hvtimesync* at vmbus? # Hyper-V Timesync # Pull in optional local configuration cinclude "arch/amd64/conf/GENERIC.local" diff --git a/sys/arch/x86/conf/files.x86 b/sys/arch/x86/conf/files.x86 index 061308304c9..f4ae0dfc39c 100644 --- a/sys/arch/x86/conf/files.x86 +++ b/sys/arch/x86/conf/files.x86 @@ -83,19 +83,19 @@ file arch/x86/x86/vmbus.c vmbus needs-flag device hvheartbeat attach hvheartbeat at hypervvmbus -file arch/x86/x86/hvheartbeat_vmbus.c hvheartbeat +file arch/x86/x86/hvheartbeat.c hvheartbeat device hvkvp attach hvkvp at hypervvmbus -file arch/x86/x86/hvkvp_vmbus.c hvkvp +file arch/x86/x86/hvkvp.c hvkvp -device hvshutdown +device hvshutdown: sysmon_power, sysmon_taskq attach hvshutdown at hypervvmbus -file arch/x86/x86/hvshutdown_vmbus.c hvshutdown +file arch/x86/x86/hvshutdown.c hvshutdown device hvtimesync attach hvtimesync at hypervvmbus -file arch/x86/x86/hvtimesync_vmbus.c hvtimesync +file arch/x86/x86/hvtimesync.c hvtimesync file arch/x86/x86/vmbusic.c hvheartbeat | hvkvp | hvshutdown | hvtimesync diff --git a/sys/arch/x86/x86/hvheartbeat.c b/sys/arch/x86/x86/hvheartbeat.c new file mode 100644 index 00000000000..5d7d30a3514 --- /dev/null +++ b/sys/arch/x86/x86/hvheartbeat.c @@ -0,0 +1,199 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2014,2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifdef __KERNEL_RCSID +__KERNEL_RCSID(0, "$NetBSD$"); +#endif +#ifdef __FBSDID +__FBSDID("$FreeBSD: head/sys/dev/hyperv/utilities/vmbus_heartbeat.c 310324 2016-12-20 09:46:14Z sephe $"); +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VMBUS_HEARTBEAT_FWVER_MAJOR 3 +#define VMBUS_HEARTBEAT_FWVER \ + VMBUS_IC_VERSION(VMBUS_HEARTBEAT_FWVER_MAJOR, 0) + +#define VMBUS_HEARTBEAT_MSGVER_MAJOR 3 +#define VMBUS_HEARTBEAT_MSGVER \ + VMBUS_IC_VERSION(VMBUS_HEARTBEAT_MSGVER_MAJOR, 0) + +static int hvheartbeat_match(device_t, cfdata_t, void *); +static void hvheartbeat_attach(device_t, device_t, void *); +static int hvheartbeat_detach(device_t, int); + +static void hvheartbeat_channel_cb(void *); + +struct hvheartbeat_softc { + struct vmbusic_softc sc_vmbusic; +}; + +CFATTACH_DECL_NEW(hvheartbeat, sizeof(struct hvheartbeat_softc), + hvheartbeat_match, hvheartbeat_attach, hvheartbeat_detach, NULL); + +static int +hvheartbeat_match(device_t parent, cfdata_t cf, void *aux) +{ + struct vmbus_attach_args *aa = aux; + + return vmbusic_probe(aa, &hyperv_guid_heartbeat); +} + +static void +hvheartbeat_attach(device_t parent, device_t self, void *aux) +{ + struct vmbus_attach_args *aa = aux; + int error; + + aprint_naive("\n"); + aprint_normal(": Hyper-V Heartbeat\n"); + + error = vmbusic_attach(self, aa, hvheartbeat_channel_cb); + if (error) + return; + + (void) pmf_device_register(self, NULL, NULL); +} + +static int +hvheartbeat_detach(device_t self, int flags) +{ + int error; + + error = vmbusic_detach(self, flags); + if (error) + return error; + + pmf_device_deregister(self); + + return 0; +} + +static void +hvheartbeat_channel_cb(void *arg) +{ + struct hvheartbeat_softc *sc = arg; + struct vmbusic_softc *vsc = &sc->sc_vmbusic; + struct vmbus_channel *ch = vsc->sc_chan; + struct vmbus_icmsg_hdr *hdr; + struct vmbus_icmsg_heartbeat *msg; + uint64_t rid; + uint32_t rlen; + int error; + + error = vmbus_channel_recv(ch, vsc->sc_buf, vsc->sc_buflen, + &rlen, &rid, 0); + if (error || rlen == 0) { + if (error != EAGAIN) { + DPRINTF("%s: heartbeat error=%d len=%u\n", + device_xname(vsc->sc_dev), error, rlen); + } + return; + } + if (rlen < sizeof(*hdr)) { + DPRINTF("%s: heartbeat short read len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + hdr = (struct vmbus_icmsg_hdr *)vsc->sc_buf; + switch (hdr->ic_type) { + case VMBUS_ICMSG_TYPE_NEGOTIATE: + error = vmbusic_negotiate(vsc, hdr, &rlen, + VMBUS_HEARTBEAT_FWVER, VMBUS_HEARTBEAT_MSGVER); + if (error) + return; + break; + + case VMBUS_ICMSG_TYPE_HEARTBEAT: + if (rlen < VMBUS_ICMSG_HEARTBEAT_SIZE_MIN) { + DPRINTF("%s: invalid heartbeat len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + msg = (struct vmbus_icmsg_heartbeat *)hdr; + msg->ic_seq++; + break; + + default: + aprint_error_dev(vsc->sc_dev, + "unhandled heartbeat message type %u\n", hdr->ic_type); + return; + } + + (void) vmbusic_sendresp(vsc, ch, vsc->sc_buf, rlen, rid); +} + +MODULE(MODULE_CLASS_DRIVER, hvheartbeat, "vmbus"); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +hvheartbeat_modcmd(modcmd_t cmd, void *aux) +{ + int error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_hvheartbeat, + cfattach_ioconf_hvheartbeat, cfdata_ioconf_hvheartbeat); +#endif + break; + + case MODULE_CMD_FINI: +#ifdef _MODULE + error = config_fini_component(cfdriver_ioconf_hvheartbeat, + cfattach_ioconf_hvheartbeat, cfdata_ioconf_hvheartbeat); +#endif + break; + + case MODULE_CMD_AUTOUNLOAD: + error = EBUSY; + break; + + default: + error = ENOTTY; + break; + } + + return error; +} diff --git a/sys/arch/x86/x86/hvshutdown.c b/sys/arch/x86/x86/hvshutdown.c new file mode 100644 index 00000000000..c7eeb3d7efa --- /dev/null +++ b/sys/arch/x86/x86/hvshutdown.c @@ -0,0 +1,234 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2014,2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifdef __KERNEL_RCSID +__KERNEL_RCSID(0, "$NetBSD$"); +#endif +#ifdef __FBSDID +__FBSDID("$FreeBSD: head/sys/dev/hyperv/utilities/vmbus_shutdown.c 310324 2016-12-20 09:46:14Z sephe $"); +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#define VMBUS_SHUTDOWN_FWVER_MAJOR 3 +#define VMBUS_SHUTDOWN_FWVER \ + VMBUS_IC_VERSION(VMBUS_SHUTDOWN_FWVER_MAJOR, 0) + +#define VMBUS_SHUTDOWN_MSGVER_MAJOR 3 +#define VMBUS_SHUTDOWN_MSGVER \ + VMBUS_IC_VERSION(VMBUS_SHUTDOWN_MSGVER_MAJOR, 0) + +static int hvshutdown_match(device_t, cfdata_t, void *); +static void hvshutdown_attach(device_t, device_t, void *); +static int hvshutdown_detach(device_t, int); + +static void hvshutdown_channel_cb(void *); + +struct hvshutdown_softc { + struct vmbusic_softc sc_vmbusic; + + struct sysmon_pswitch sc_smpsw; +}; + +CFATTACH_DECL_NEW(hvshutdown, sizeof(struct hvshutdown_softc), + hvshutdown_match, hvshutdown_attach, hvshutdown_detach, NULL); + +static int +hvshutdown_match(device_t parent, cfdata_t cf, void *aux) +{ + struct vmbus_attach_args *aa = aux; + + return vmbusic_probe(aa, &hyperv_guid_shutdown); +} + +static void +hvshutdown_attach(device_t parent, device_t self, void *aux) +{ + struct hvshutdown_softc *sc = device_private(self); + struct vmbus_attach_args *aa = aux; + int error; + + aprint_naive("\n"); + aprint_normal(": Hyper-V Shutdown\n"); + + error = vmbusic_attach(self, aa, hvshutdown_channel_cb); + if (error) + return; + + (void) pmf_device_register(self, NULL, NULL); + + sysmon_task_queue_init(); + + sc->sc_smpsw.smpsw_name = device_xname(self); + sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_POWER; + (void) sysmon_pswitch_register(&sc->sc_smpsw); +} + +static int +hvshutdown_detach(device_t self, int flags) +{ + struct hvshutdown_softc *sc = device_private(self); + int error; + + error = vmbusic_detach(self, flags); + if (error) + return error; + + pmf_device_deregister(self); + sysmon_pswitch_unregister(&sc->sc_smpsw); + + return 0; +} + +static void +hvshutdown_do_shutdown(void *arg) +{ + struct hvshutdown_softc *sc = arg; + + sysmon_pswitch_event(&sc->sc_smpsw, PSWITCH_EVENT_PRESSED); +} + +static void +hvshutdown_channel_cb(void *arg) +{ + struct hvshutdown_softc *sc = arg; + struct vmbusic_softc *vsc = &sc->sc_vmbusic; + struct vmbus_channel *ch = vsc->sc_chan; + struct vmbus_icmsg_hdr *hdr; + struct vmbus_icmsg_shutdown *msg; + uint64_t rid; + uint32_t rlen; + int error; + bool do_shutdown = false; + + error = vmbus_channel_recv(ch, vsc->sc_buf, vsc->sc_buflen, + &rlen, &rid, 0); + if (error || rlen == 0) { + if (error != EAGAIN) { + DPRINTF("%s: shutdown error=%d len=%u\n", + device_xname(vsc->sc_dev), error, rlen); + } + return; + } + if (rlen < sizeof(*hdr)) { + DPRINTF("%s: shutdown short read len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + hdr = (struct vmbus_icmsg_hdr *)vsc->sc_buf; + switch (hdr->ic_type) { + case VMBUS_ICMSG_TYPE_NEGOTIATE: + error = vmbusic_negotiate(vsc, hdr, &rlen, VMBUS_SHUTDOWN_FWVER, + VMBUS_SHUTDOWN_MSGVER); + if (error) + return; + break; + + case VMBUS_ICMSG_TYPE_SHUTDOWN: + if (rlen < VMBUS_ICMSG_SHUTDOWN_SIZE_MIN) { + DPRINTF("%s: invalid shutdown len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + msg = (struct vmbus_icmsg_shutdown *)hdr; + if (msg->ic_haltflags == 0 || msg->ic_haltflags == 1) { + aprint_normal_dev(vsc->sc_dev, "shutdown requested\n"); + hdr->ic_status = VMBUS_ICMSG_STATUS_OK; + do_shutdown = true; + } else { + aprint_error_dev(vsc->sc_dev, + "unknown shutdown flags 0x%08x\n", + msg->ic_haltflags); + hdr->ic_status = VMBUS_ICMSG_STATUS_FAIL; + } + break; + + default: + aprint_error_dev(vsc->sc_dev, + "unhandled shutdown message type %u\n", hdr->ic_type); + return; + } + + (void) vmbusic_sendresp(vsc, ch, vsc->sc_buf, rlen, rid); + + if (do_shutdown) + sysmon_task_queue_sched(0, hvshutdown_do_shutdown, sc); +} + +MODULE(MODULE_CLASS_DRIVER, hvshutdown, "vmbus"); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +hvshutdown_modcmd(modcmd_t cmd, void *aux) +{ + int error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_hvshutdown, + cfattach_ioconf_hvshutdown, cfdata_ioconf_hvshutdown); +#endif + break; + + case MODULE_CMD_FINI: +#ifdef _MODULE + error = config_fini_component(cfdriver_ioconf_hvshutdown, + cfattach_ioconf_hvshutdown, cfdata_ioconf_hvshutdown); +#endif + break; + + case MODULE_CMD_AUTOUNLOAD: + error = EBUSY; + break; + + default: + error = ENOTTY; + break; + } + + return error; +} diff --git a/sys/arch/x86/x86/hvtimesync.c b/sys/arch/x86/x86/hvtimesync.c new file mode 100644 index 00000000000..a5645e0e7c8 --- /dev/null +++ b/sys/arch/x86/x86/hvtimesync.c @@ -0,0 +1,316 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2014,2016-2017 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifdef __KERNEL_RCSID +__KERNEL_RCSID(0, "$NetBSD$"); +#endif +#ifdef __FBSDID +__FBSDID("$FreeBSD: head/sys/dev/hyperv/utilities/vmbus_timesync.c 322488 2017-08-14 06:00:50Z sephe $"); +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VMBUS_TIMESYNC_FWVER_MAJOR 3 +#define VMBUS_TIMESYNC_FWVER \ + VMBUS_IC_VERSION(VMBUS_TIMESYNC_FWVER_MAJOR, 0) + +#define VMBUS_TIMESYNC_MSGVER_MAJOR 4 +#define VMBUS_TIMESYNC_MSGVER \ + VMBUS_IC_VERSION(VMBUS_TIMESYNC_MSGVER_MAJOR, 0) + +#define VMBUS_TIMESYNC_MSGVER4(sc) \ + VMBUS_ICVER_LE(VMBUS_IC_VERSION(4, 0), (sc)->sc_vmbusic.sc_msgver) + +#define VMBUS_TIMESYNC_DORTT(sc) \ + (VMBUS_TIMESYNC_MSGVER4((sc)) && (hyperv_tc64 != NULL)) + +static int hvtimesync_match(device_t, cfdata_t, void *); +static void hvtimesync_attach(device_t, device_t, void *); +static int hvtimesync_detach(device_t, int); + +static void hvtimesync_channel_cb(void *); +static int hvtimesync_sysctl_setup(device_t); + +struct hvtimesync_softc { + struct vmbusic_softc sc_vmbusic; +}; + +CFATTACH_DECL_NEW(hvtimesync, sizeof(struct hvtimesync_softc), + hvtimesync_match, hvtimesync_attach, hvtimesync_detach, NULL); + +static int hvtimesync_ignore_sync; +static int hvtimesnyc_sample_verbose; +static int hvtimesync_sample_thresh = -1; + +static int +hvtimesync_match(device_t parent, cfdata_t cf, void *aux) +{ + struct vmbus_attach_args *aa = aux; + + return vmbusic_probe(aa, &hyperv_guid_timesync); +} + +static void +hvtimesync_attach(device_t parent, device_t self, void *aux) +{ + struct vmbus_attach_args *aa = aux; + int error; + + aprint_naive("\n"); + aprint_normal(": Hyper-V Timesync\n"); + + error = vmbusic_attach(self, aa, hvtimesync_channel_cb); + if (error) + return; + + (void) pmf_device_register(self, NULL, NULL); + + (void) hvtimesync_sysctl_setup(self); +} + +static int +hvtimesync_detach(device_t self, int flags) +{ + int error; + + error = vmbusic_detach(self, flags); + if (error) + return error; + + pmf_device_deregister(self); + + return 0; +} + +static void +do_timesync(struct hvtimesync_softc *sc, uint64_t hvtime, uint64_t sent_tc, + uint8_t tsflags) +{ + struct vmbusic_softc *vsc = &sc->sc_vmbusic; + struct timespec vm_ts, hv_ts; + uint64_t hv_ns, vm_ns, rtt = 0; + int64_t diff; + + if (VMBUS_TIMESYNC_DORTT(sc)) + rtt = hyperv_tc64() - sent_tc; + + hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE + rtt) * HYPERV_TIMER_NS_FACTOR; + nanotime(&vm_ts); + vm_ns = (vm_ts.tv_sec * NANOSECOND) + vm_ts.tv_nsec; + + if ((tsflags & VMBUS_ICMSG_TS_FLAG_SYNC) && !hvtimesync_ignore_sync) { + aprint_verbose_dev(vsc->sc_dev, + "apply sync request, hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); + hv_ts.tv_sec = hv_ns / NANOSECOND; + hv_ts.tv_nsec = hv_ns % NANOSECOND; + tc_setclock(&hv_ts); + /* Done! */ + return; + } + + if ((tsflags & VMBUS_ICMSG_TS_FLAG_SAMPLE) && + hvtimesync_sample_thresh >= 0) { + if (hvtimesnyc_sample_verbose) { + aprint_normal_dev(vsc->sc_dev, + "sample request, hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); + } + + if (hv_ns > vm_ns) + diff = hv_ns - vm_ns; + else + diff = vm_ns - hv_ns; + /* nanosec -> millisec */ + diff /= 1000000; + + if (diff > hvtimesync_sample_thresh) { + aprint_normal_dev(vsc->sc_dev, + "apply sample request, hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); + hv_ts.tv_sec = hv_ns / NANOSECOND; + hv_ts.tv_nsec = hv_ns % NANOSECOND; + tc_setclock(&hv_ts); + } + /* Done */ + return; + } +} + +static void +hvtimesync_channel_cb(void *arg) +{ + struct hvtimesync_softc *sc = arg; + struct vmbusic_softc *vsc = &sc->sc_vmbusic; + struct vmbus_channel *ch = vsc->sc_chan; + struct vmbus_icmsg_hdr *hdr; + uint64_t rid; + uint32_t rlen; + int error; + + error = vmbus_channel_recv(ch, vsc->sc_buf, vsc->sc_buflen, + &rlen, &rid, 0); + if (error || rlen == 0) { + if (error != EAGAIN) { + DPRINTF("%s: timesync error=%d len=%u\n", + device_xname(vsc->sc_dev), error, rlen); + } + return; + } + if (rlen < sizeof(*hdr)) { + DPRINTF("%s: hvtimesync short read len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + hdr = (struct vmbus_icmsg_hdr *)vsc->sc_buf; + switch (hdr->ic_type) { + case VMBUS_ICMSG_TYPE_NEGOTIATE: + error = vmbusic_negotiate(vsc, hdr, &rlen, VMBUS_TIMESYNC_FWVER, + VMBUS_TIMESYNC_MSGVER); + if (error) + return; + if (VMBUS_TIMESYNC_DORTT(sc)) { + DPRINTF("%s: RTT\n", device_xname(vsc->sc_dev)); + } + break; + + case VMBUS_ICMSG_TYPE_TIMESYNC: + if (VMBUS_TIMESYNC_MSGVER4(sc)) { + struct vmbus_icmsg_timesync4 *msg4; + + if (rlen < sizeof(*msg4)) { + DPRINTF("%s: invalid timesync4 len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + msg4 = (struct vmbus_icmsg_timesync4 *)hdr; + do_timesync(sc, msg4->ic_hvtime, msg4->ic_sent_tc, + msg4->ic_tsflags); + } else { + struct vmbus_icmsg_timesync *msg; + + if (rlen < sizeof(*msg)) { + DPRINTF("%s: invalid timesync len=%u\n", + device_xname(vsc->sc_dev), rlen); + return; + } + + msg = (struct vmbus_icmsg_timesync *)hdr; + do_timesync(sc, msg->ic_hvtime, 0, msg->ic_tsflags); + } + break; + + default: + aprint_error_dev(vsc->sc_dev, + "unhandled _timesync message type %u\n", hdr->ic_type); + return; + } + + (void) vmbusic_sendresp(vsc, ch, vsc->sc_buf, rlen, rid); +} + +static int +hvtimesync_sysctl_setup(device_t self) +{ + const struct sysctlnode *node; + struct hvtimesync_softc *sc = device_private(self); + struct vmbusic_softc *vsc = &sc->sc_vmbusic; + int error; + + if (hyperv_sysctl_node == NULL) + return ENXIO; + + error = sysctl_createv(&vsc->sc_log, 0, &hyperv_sysctl_node, &node, + 0, CTLTYPE_NODE, "timesync", NULL, + NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); + if (error) + goto fail; + + /* XXX sysctl hvtimesync_ignore_sync */ + /* XXX sysctl hvtimesnyc_sample_verbose */ + /* XXX sysctl hvtimesync_sample_thresh */ + + return 0; + +fail: + sysctl_teardown(&vsc->sc_log); + vsc->sc_log = NULL; + return error; +} + +MODULE(MODULE_CLASS_DRIVER, hvtimesync, "vmbus"); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +hvtimesync_modcmd(modcmd_t cmd, void *aux) +{ + int error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_hvtimesync, + cfattach_ioconf_hvtimesync, cfdata_ioconf_hvtimesync); +#endif + break; + + case MODULE_CMD_FINI: +#ifdef _MODULE + error = config_fini_component(cfdriver_ioconf_hvtimesync, + cfattach_ioconf_hvtimesync, cfdata_ioconf_hvtimesync); +#endif + break; + + case MODULE_CMD_AUTOUNLOAD: + error = EBUSY; + break; + + default: + error = ENOTTY; + break; + } + + return error; +} diff --git a/sys/arch/x86/x86/vmbusic.c b/sys/arch/x86/x86/vmbusic.c new file mode 100644 index 00000000000..59bbb9d3662 --- /dev/null +++ b/sys/arch/x86/x86/vmbusic.c @@ -0,0 +1,272 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2014,2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifdef __KERNEL_RCSID +__KERNEL_RCSID(0, "$NetBSD$"); +#endif +#ifdef __FBSDID +__FBSDID("$FreeBSD: head/sys/dev/hyperv/utilities/vmbus_ic.c 310317 2016-12-20 07:14:24Z sephe $"); +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VMBUS_IC_BRSIZE (4 * PAGE_SIZE) + +#define VMBUS_IC_VERCNT 2 +#define VMBUS_IC_NEGOSZ \ + offsetof(struct vmbus_icmsg_negotiate, ic_ver[VMBUS_IC_VERCNT]) +__CTASSERT(VMBUS_IC_NEGOSZ < VMBUS_IC_BRSIZE); + + +int +vmbusic_probe(struct vmbus_attach_args *aa, const struct hyperv_guid *guid) +{ + + if (memcmp(aa->aa_type, guid, sizeof(*aa->aa_type)) != 0) + return 0; + return 1; +} + +int +vmbusic_attach(device_t dv, struct vmbus_attach_args *aa, + vmbus_channel_callback_t cb) +{ + struct vmbusic_softc *sc = device_private(dv); + + sc->sc_dev = dv; + sc->sc_chan = aa->aa_chan; + + sc->sc_buflen = VMBUS_IC_BRSIZE; + sc->sc_buf = kmem_alloc(sc->sc_buflen, KM_SLEEP); + + /* + * These services are not performance critical and do not need + * batched reading. Furthermore, some services such as KVP can + * only handle one message from the host at a time. + * Turn off batched reading for all util drivers before we open the + * channel. + */ + sc->sc_chan->ch_flags &= ~CHF_BATCHED; + + if (vmbus_channel_open(sc->sc_chan, sc->sc_buflen, NULL, 0, cb, sc)) { + aprint_error_dev(dv, "failed to open channel\n"); + kmem_free(sc->sc_buf, sc->sc_buflen); + sc->sc_buf = NULL; + return ENXIO; + } + + return 0; +} + +int +vmbusic_detach(device_t dv, int flags) +{ + struct vmbusic_softc *sc = device_private(dv); + int error; + + error = vmbus_channel_close(sc->sc_chan); + if (error != 0) + return error; + + if (sc->sc_buf != NULL) { + kmem_free(sc->sc_buf, sc->sc_buflen); + sc->sc_buf = NULL; + } + + if (sc->sc_log != NULL) { + sysctl_teardown(&sc->sc_log); + sc->sc_log = NULL; + } + + return 0; +} + +int +vmbusic_negotiate(struct vmbusic_softc *sc, void *data, uint32_t *dlen0, + uint32_t fw_ver, uint32_t msg_ver) +{ + struct vmbus_icmsg_negotiate *nego; + uint32_t sel_fw_ver = 0, sel_msg_ver = 0; + int i, cnt, dlen = *dlen0, error; + bool has_fw_ver, has_msg_ver = false; + + /* + * Preliminary message verification. + */ + if (dlen < sizeof(*nego)) { + aprint_error_dev(sc->sc_dev, "truncated ic negotiate, len %d\n", + dlen); + return EINVAL; + } + nego = data; + + if (nego->ic_fwver_cnt == 0) { + aprint_error_dev(sc->sc_dev, "ic negotiate does not contain " + "framework version %u\n", nego->ic_fwver_cnt); + return EINVAL; + } + if (nego->ic_msgver_cnt == 0) { + aprint_error_dev(sc->sc_dev, "ic negotiate does not contain " + "message version %u\n", nego->ic_msgver_cnt); + return EINVAL; + } + + cnt = nego->ic_fwver_cnt + nego->ic_msgver_cnt; + if (dlen < offsetof(struct vmbus_icmsg_negotiate, ic_ver[cnt])) { + aprint_error_dev(sc->sc_dev, "ic negotiate does not contain " + "versions %d\n", dlen); + return EINVAL; + } + + error = EOPNOTSUPP; + + /* + * Find the best match framework version. + */ + has_fw_ver = false; + for (i = 0; i < nego->ic_fwver_cnt; ++i) { + if (VMBUS_ICVER_LE(nego->ic_ver[i], fw_ver)) { + if (!has_fw_ver) { + sel_fw_ver = nego->ic_ver[i]; + has_fw_ver = true; + } else if (VMBUS_ICVER_GT(nego->ic_ver[i], + sel_fw_ver)) { + sel_fw_ver = nego->ic_ver[i]; + } + } + } + if (!has_fw_ver) { + aprint_error_dev(sc->sc_dev, "failed to select framework " + "version\n"); + goto done; + } + + /* + * Fine the best match message version. + */ + has_msg_ver = false; + for (i = nego->ic_fwver_cnt; + i < nego->ic_fwver_cnt + nego->ic_msgver_cnt; ++i) { + if (VMBUS_ICVER_LE(nego->ic_ver[i], msg_ver)) { + if (!has_msg_ver) { + sel_msg_ver = nego->ic_ver[i]; + has_msg_ver = true; + } else if (VMBUS_ICVER_GT(nego->ic_ver[i], + sel_msg_ver)) { + sel_msg_ver = nego->ic_ver[i]; + } + } + } + if (!has_msg_ver) { + aprint_error_dev(sc->sc_dev, "failed to select message " + "version\n"); + goto done; + } + + error = 0; +done: + if (bootverbose || !has_fw_ver || !has_msg_ver) { + if (has_fw_ver) { + aprint_verbose_dev(sc->sc_dev, + "sel framework version: %u.%u\n", + VMBUS_ICVER_MAJOR(sel_fw_ver), + VMBUS_ICVER_MINOR(sel_fw_ver)); + } + for (i = 0; i < nego->ic_fwver_cnt; i++) { + aprint_error_dev(sc->sc_dev, + "supp framework version: %u.%u\n", + VMBUS_ICVER_MAJOR(nego->ic_ver[i]), + VMBUS_ICVER_MINOR(nego->ic_ver[i])); + } + + if (has_msg_ver) { + aprint_verbose_dev(sc->sc_dev, + "sel message version: %u.%u\n", + VMBUS_ICVER_MAJOR(sel_msg_ver), + VMBUS_ICVER_MINOR(sel_msg_ver)); + } + for (i = nego->ic_fwver_cnt; + i < nego->ic_fwver_cnt + nego->ic_msgver_cnt; i++) { + aprint_error_dev(sc->sc_dev, + "supp message version: %u.%u\n", + VMBUS_ICVER_MAJOR(nego->ic_ver[i]), + VMBUS_ICVER_MINOR(nego->ic_ver[i])); + } + } + if (error) + return error; + + /* Record the selected versions. */ + sc->sc_fwver = sel_fw_ver; + sc->sc_msgver = sel_msg_ver; + + /* One framework version. */ + nego->ic_fwver_cnt = 1; + nego->ic_ver[0] = sel_fw_ver; + + /* One message version. */ + nego->ic_msgver_cnt = 1; + nego->ic_ver[1] = sel_msg_ver; + + /* Update data size. */ + nego->ic_hdr.ic_dsize = VMBUS_IC_NEGOSZ - + sizeof(struct vmbus_icmsg_hdr); + + /* Update total size, if necessary. */ + if (dlen < VMBUS_IC_NEGOSZ) + *dlen0 = VMBUS_IC_NEGOSZ; + + return 0; +} + +int +vmbusic_sendresp(struct vmbusic_softc *sc, struct vmbus_channel *chan, + void *data, uint32_t dlen, uint64_t rid) +{ + struct vmbus_icmsg_hdr *hdr; + int error; + + KASSERTMSG(dlen >= sizeof(*hdr), "invalid data length %d", dlen); + hdr = data; + + hdr->ic_flags = VMBUS_ICMSG_FLAG_TRANSACTION|VMBUS_ICMSG_FLAG_RESPONSE; + error = vmbus_channel_send(chan, data, dlen, rid, + VMBUS_CHANPKT_TYPE_INBAND, 0); + if (error != 0) + aprint_error_dev(sc->sc_dev, "resp send failed: %d\n", error); + return error; +} diff --git a/sys/arch/x86/x86/vmbusicreg.h b/sys/arch/x86/x86/vmbusicreg.h new file mode 100644 index 00000000000..6c9f00e81d0 --- /dev/null +++ b/sys/arch/x86/x86/vmbusicreg.h @@ -0,0 +1,248 @@ +/* $NetBSD$ */ +/* $OpenBSD: hypervicreg.h,v 1.6 2017/11/07 16:49:42 mikeb Exp $ */ + +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/sys/dev/hyperv/utilities/vmbus_icreg.h 305281 2016-09-02 06:23:28Z sephe $ + */ + +#ifndef _VMBUSICREG_H_ +#define _VMBUSICREG_H_ + +#define VMBUS_IC_BUFRINGSIZE (4 * PAGE_SIZE) + +#define VMBUS_ICMSG_TYPE_NEGOTIATE 0 +#define VMBUS_ICMSG_TYPE_HEARTBEAT 1 +#define VMBUS_ICMSG_TYPE_KVP 2 +#define VMBUS_ICMSG_TYPE_SHUTDOWN 3 +#define VMBUS_ICMSG_TYPE_TIMESYNC 4 +#define VMBUS_ICMSG_TYPE_VSS 5 + +#define VMBUS_ICMSG_STATUS_OK 0x00000000 +#define VMBUS_ICMSG_STATUS_FAIL 0x80004005 + +#define VMBUS_IC_VERSION(major, minor) ((major) | (((uint32_t)(minor)) << 16)) +#define VMBUS_ICVER_MAJOR(ver) ((ver) & 0xffff) +#define VMBUS_ICVER_MINOR(ver) (((ver) & 0xffff0000) >> 16) +#define VMBUS_ICVER_SWAP(ver) \ + ((VMBUS_ICVER_MAJOR((ver)) << 16) | VMBUS_ICVER_MINOR((ver))) +#define VMBUS_ICVER_LE(v1, v2) \ + (VMBUS_ICVER_SWAP((v1)) <= VMBUS_ICVER_SWAP((v2))) +#define VMBUS_ICVER_GT(v1, v2) \ + (VMBUS_ICVER_SWAP((v1)) > VMBUS_ICVER_SWAP((v2))) + +struct vmbus_pipe_hdr { + uint32_t ph_flags; + uint32_t ph_msgsz; +} __packed; + +struct vmbus_icmsg_hdr { + struct vmbus_pipe_hdr ic_pipe; + uint32_t ic_fwver; /* framework version */ + uint16_t ic_type; + uint32_t ic_msgver; /* message version */ + uint16_t ic_dsize; /* data size */ + uint32_t ic_status; /* VMBUS_ICMSG_STATUS_ */ + uint8_t ic_tid; + uint8_t ic_flags; /* VMBUS_ICMSG_FLAG_ */ + uint8_t ic_rsvd[2]; +} __packed; + +#define VMBUS_ICMSG_FLAG_TRANSACTION 1 +#define VMBUS_ICMSG_FLAG_REQUEST 2 +#define VMBUS_ICMSG_FLAG_RESPONSE 4 + +/* VMBUS_ICMSG_TYPE_NEGOTIATE */ +struct vmbus_icmsg_negotiate { + struct vmbus_icmsg_hdr ic_hdr; + uint16_t ic_fwver_cnt; + uint16_t ic_msgver_cnt; + uint32_t ic_rsvd; + /* + * This version array contains two set of supported + * versions: + * - The first set consists of #ic_fwver_cnt supported framework + * versions. + * - The second set consists of #ic_msgver_cnt supported message + * versions. + */ + uint32_t ic_ver[0]; +} __packed; + +/* VMBUS_ICMSG_TYPE_HEARTBEAT */ +struct vmbus_icmsg_heartbeat { + struct vmbus_icmsg_hdr ic_hdr; + uint64_t ic_seq; + uint32_t ic_rsvd[8]; +} __packed; + +#define VMBUS_ICMSG_HEARTBEAT_SIZE_MIN \ + offsetof(struct vmbus_icmsg_heartbeat, ic_rsvd[0]) + +/* VMBUS_ICMSG_TYPE_SHUTDOWN */ +struct vmbus_icmsg_shutdown { + struct vmbus_icmsg_hdr ic_hdr; + uint32_t ic_code; + uint32_t ic_timeo; + uint32_t ic_haltflags; + uint8_t ic_msg[2048]; +} __packed; + +#define VMBUS_ICMSG_SHUTDOWN_SIZE_MIN \ + offsetof(struct vmbus_icmsg_shutdown, ic_msg[0]) + +/* VMBUS_ICMSG_TYPE_TIMESYNC */ +struct vmbus_icmsg_timesync { + struct vmbus_icmsg_hdr ic_hdr; + uint64_t ic_hvtime; + uint64_t ic_vmtime; + uint64_t ic_rtt; + uint8_t ic_tsflags; /* VMBUS_ICMSG_TS_FLAG_ */ +} __packed; + +/* VMBUS_ICMSG_TYPE_TIMESYNC, MSGVER4 */ +struct vmbus_icmsg_timesync4 { + struct vmbus_icmsg_hdr ic_hdr; + uint64_t ic_hvtime; + uint64_t ic_sent_tc; + uint8_t ic_tsflags; /* VMBUS_ICMSG_TS_FLAG_ */ + uint8_t ic_rsvd[5]; +} __packed; + +#define VMBUS_ICMSG_TS_FLAG_SYNC 0x01 +#define VMBUS_ICMSG_TS_FLAG_SAMPLE 0x02 + +#define VMBUS_ICMSG_TS_BASE 116444736000000000ULL + +/* Registry value types */ +#define VMBUS_KVP_REG_SZ 1 +#define VMBUS_KVP_REG_U32 4 +#define VMBUS_KVP_REG_U64 8 + +/* Hyper-V status codes */ +#define VMBUS_KVP_S_OK 0x00000000 +#define VMBUS_KVP_E_FAIL 0x80004005 +#define VMBUS_KVP_S_CONT 0x80070103 + +#define VMBUS_KVP_MAX_VAL_SIZE 2048 +#define VMBUS_KVP_MAX_KEY_SIZE 512 + +enum vmbus_kvp_op { + VMBUS_KVP_OP_GET = 0, + VMBUS_KVP_OP_SET, + VMBUS_KVP_OP_DELETE, + VMBUS_KVP_OP_ENUMERATE, + VMBUS_KVP_OP_GET_IP_INFO, + VMBUS_KVP_OP_SET_IP_INFO, + VMBUS_KVP_OP_COUNT +}; + +enum vmbus_kvp_pool { + VMBUS_KVP_POOL_EXTERNAL = 0, + VMBUS_KVP_POOL_GUEST, + VMBUS_KVP_POOL_AUTO, + VMBUS_KVP_POOL_AUTO_EXTERNAL, + VMBUS_KVP_POOL_COUNT +}; + +union vmbus_kvp_hdr { + struct { + uint8_t kvu_op; + uint8_t kvu_pool; + uint16_t kvu_pad; + } req; + struct { + uint32_t kvu_err; + } rsp; +#define kvh_op req.kvu_op +#define kvh_pool req.kvu_pool +#define kvh_err rsp.kvu_err +} __packed; + +struct vmbus_kvp_msg_val { + uint32_t kvm_valtype; + uint32_t kvm_keylen; + uint32_t kvm_vallen; + uint8_t kvm_key[VMBUS_KVP_MAX_KEY_SIZE]; + uint8_t kvm_val[VMBUS_KVP_MAX_VAL_SIZE]; +} __packed; + +struct vmbus_kvp_msg_enum { + uint32_t kvm_index; + uint32_t kvm_valtype; + uint32_t kvm_keylen; + uint32_t kvm_vallen; + uint8_t kvm_key[VMBUS_KVP_MAX_KEY_SIZE]; + uint8_t kvm_val[VMBUS_KVP_MAX_VAL_SIZE]; +} __packed; + +struct vmbus_kvp_msg_del { + uint32_t kvm_keylen; + uint8_t kvm_key[VMBUS_KVP_MAX_KEY_SIZE]; +} __packed; + +#define ADDR_FAMILY_NONE 0x00 +#define ADDR_FAMILY_IPV4 0x01 +#define ADDR_FAMILY_IPV6 0x02 + +#define MAX_MAC_ADDR_SIZE 256 +#define MAX_IP_ADDR_SIZE 2048 +#define MAX_GATEWAY_SIZE 1024 + +struct vmbus_kvp_msg_addr { + uint8_t kvm_mac[MAX_MAC_ADDR_SIZE]; + uint8_t kvm_family; + uint8_t kvm_dhcp; + uint8_t kvm_addr[MAX_IP_ADDR_SIZE]; + uint8_t kvm_netmask[MAX_IP_ADDR_SIZE]; + uint8_t kvm_gateway[MAX_GATEWAY_SIZE]; + uint8_t kvm_dns[MAX_IP_ADDR_SIZE]; +} __packed; + +union vmbus_kvp_msg { + struct vmbus_kvp_msg_val kvm_val; + struct vmbus_kvp_msg_enum kvm_enum; + struct vmbus_kvp_msg_del kvm_del; +}; + +struct vmbus_icmsg_kvp { + struct vmbus_icmsg_hdr ic_hdr; + union vmbus_kvp_hdr ic_kvh; + union vmbus_kvp_msg ic_kvm; +} __packed; + +struct vmbus_icmsg_kvp_addr { + struct vmbus_icmsg_hdr ic_hdr; + struct { + struct { + uint8_t kvu_op; + uint8_t kvu_pool; + } req; + } ic_kvh; + struct vmbus_kvp_msg_addr ic_kvm; +} __packed; + +#endif /* _VMBUSICREG_H_ */ diff --git a/sys/arch/x86/x86/vmbusicvar.h b/sys/arch/x86/x86/vmbusicvar.h new file mode 100644 index 00000000000..a3d451fd044 --- /dev/null +++ b/sys/arch/x86/x86/vmbusicvar.h @@ -0,0 +1,70 @@ +/* $NetBSD$ */ +/* $OpenBSD: hypervic.c,v 1.13 2017/08/10 15:25:57 mikeb Exp $ */ + +/*- + * Copyright (c) 2009-2016 Microsoft Corp. + * Copyright (c) 2012 NetApp Inc. + * Copyright (c) 2012 Citrix Inc. + * Copyright (c) 2016 Mike Belopuhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The OpenBSD port was done under funding by Esdenera Networks GmbH. + */ + +#ifndef _VMBUSICVAR_H_ +#define _VMBUSICVAR_H_ + +#include + +#include +#include +#include + +struct vmbusic_softc { + device_t sc_dev; + + struct vmbus_channel *sc_chan; + + void *sc_buf; + size_t sc_buflen; + + uint32_t sc_fwver; /* framework version */ + uint32_t sc_msgver; /* message version */ + + struct sysctllog *sc_log; +}; + +int vmbusic_probe(struct vmbus_attach_args *, const struct hyperv_guid *); +int vmbusic_attach(device_t, struct vmbus_attach_args *, + vmbus_channel_callback_t); +int vmbusic_detach(device_t, int); + +int vmbusic_negotiate(struct vmbusic_softc *, void *, uint32_t *, uint32_t, + uint32_t); +int vmbusic_sendresp(struct vmbusic_softc *, struct vmbus_channel *, + void *, uint32_t, uint64_t); + +#endif /* _VMBUSICVAR_H_ */ -- 2.17.0