void hv_event_intr(struct hv_softc *);
void hv_message_intr(struct hv_softc *);
int hv_vmbus_connect(struct hv_softc *);
-void hv_channel_response(struct hv_softc *, struct hv_channel_msg_header *);
-void hv_channel_offer(struct hv_softc *, struct hv_channel_msg_header *);
-void hv_channel_delivered(struct hv_softc *, struct hv_channel_msg_header *);
+void hv_channel_response(struct hv_softc *, struct vmbus_chanmsg_hdr *);
+void hv_channel_offer(struct hv_softc *, struct vmbus_chanmsg_hdr *);
+void hv_channel_delivered(struct hv_softc *, struct vmbus_chanmsg_hdr *);
int hv_channel_scan(struct hv_softc *);
void hv_process_offer(struct hv_softc *, struct hv_offer *);
struct hv_channel *
int hmd_response;
int hmd_request;
void (*hmd_handler)(struct hv_softc *,
- struct hv_channel_msg_header *);
+ struct vmbus_chanmsg_hdr *);
} hv_msg_dispatch[] = {
- { HV_CHANMSG_INVALID, 0, NULL },
- { HV_CHANMSG_OFFER_CHANNEL, 0, hv_channel_offer },
- { HV_CHANMSG_RESCIND_CHANNEL_OFFER, 0, NULL },
- { HV_CHANMSG_REQUEST_OFFERS, HV_CHANMSG_OFFER_CHANNEL,
+ { 0, 0, NULL },
+ { VMBUS_CHANMSG_CHOFFER, 0, hv_channel_offer },
+ { VMBUS_CHANMSG_CHRESCIND, 0, NULL },
+ { VMBUS_CHANMSG_CHREQUEST, VMBUS_CHANMSG_CHOFFER,
NULL },
- { HV_CHANMSG_ALL_OFFERS_DELIVERED, 0,
+ { VMBUS_CHANMSG_CHOFFER_DONE, 0,
hv_channel_delivered },
- { HV_CHANMSG_OPEN_CHANNEL, 0, NULL },
- { HV_CHANMSG_OPEN_CHANNEL_RESULT, HV_CHANMSG_OPEN_CHANNEL,
+ { VMBUS_CHANMSG_CHOPEN, 0, NULL },
+ { VMBUS_CHANMSG_CHOPEN_RESP, VMBUS_CHANMSG_CHOPEN,
hv_channel_response },
- { HV_CHANMSG_CLOSE_CHANNEL, 0, NULL },
- { HV_CHANMSG_GPADL_HEADER, 0, NULL },
- { HV_CHANMSG_GPADL_BODY, 0, NULL },
- { HV_CHANMSG_GPADL_CREATED, HV_CHANMSG_GPADL_HEADER,
+ { VMBUS_CHANMSG_CHCLOSE, 0, NULL },
+ { VMBUS_CHANMSG_GPADL_CONN, 0, NULL },
+ { VMBUS_CHANMSG_GPADL_SUBCONN, 0, NULL },
+ { VMBUS_CHANMSG_GPADL_CONNRESP, VMBUS_CHANMSG_GPADL_CONN,
hv_channel_response },
- { HV_CHANMSG_GPADL_TEARDOWN, 0, NULL },
- { HV_CHANMSG_GPADL_TORNDOWN, HV_CHANMSG_GPADL_TEARDOWN,
+ { VMBUS_CHANMSG_GPADL_DISCONN, 0, NULL },
+ { VMBUS_CHANMSG_GPADL_DISCONNRESP, VMBUS_CHANMSG_GPADL_DISCONN,
hv_channel_response },
- { HV_CHANMSG_REL_ID_RELEASED, 0, NULL },
- { HV_CHANMSG_INITIATED_CONTACT, 0, NULL },
- { HV_CHANMSG_VERSION_RESPONSE, HV_CHANMSG_INITIATED_CONTACT,
+ { VMBUS_CHANMSG_CHFREE, 0, NULL },
+ { VMBUS_CHANMSG_CONNECT, 0, NULL },
+ { VMBUS_CHANMSG_CONNECT_RESP, VMBUS_CHANMSG_CONNECT,
hv_channel_response },
- { HV_CHANMSG_UNLOAD, 0, NULL },
+ { VMBUS_CHANMSG_DISCONNECT, 0, NULL },
};
struct timecounter hv_timecounter = {
/* FreeBSD 10 apparently */
ver = 0x8200ULL << 48;
ver |= 10 << 16;
- wrmsr(HV_X64_MSR_GUEST_OS_ID, ver);
+ wrmsr(MSR_HV_GUEST_OS_ID, ver);
}
u_int
hv_gettime(struct timecounter *tc)
{
- u_int now = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
+ u_int now = rdmsr(MSR_HV_TIME_REF_COUNT);
return (now);
}
return (-1);
}
- msr = (atop(pa) << HV_X64_MSR_HYPERCALL_PASHIFT) |
- HV_X64_MSR_HYPERCALL_ENABLED;
- wrmsr(HV_X64_MSR_HYPERCALL, msr);
+ msr = (atop(pa) << MSR_HV_HYPERCALL_PGSHIFT) | MSR_HV_HYPERCALL_ENABLE;
+ wrmsr(MSR_HV_HYPERCALL, msr);
- if (!(rdmsr(HV_X64_MSR_HYPERCALL) & HV_X64_MSR_HYPERCALL_ENABLED)) {
+ if (!(rdmsr(MSR_HV_HYPERCALL) & MSR_HV_HYPERCALL_ENABLE)) {
printf(": failed to set up a hypercall page\n");
return (-1);
}
pmap_extract(pmap_kernel(), (vaddr_t)input, &input_pa) == 0) {
printf("%s: hypercall input PA extraction failed\n",
sc->sc_dev.dv_xname);
- return (~HV_STATUS_SUCCESS);
+ return (~HYPERCALL_STATUS_SUCCESS);
}
if (output != NULL &&
pmap_extract(pmap_kernel(), (vaddr_t)output, &output_pa) == 0) {
printf("%s: hypercall output PA extraction failed\n",
sc->sc_dev.dv_xname);
- return (~HV_STATUS_SUCCESS);
+ return (~HYPERCALL_STATUS_SUCCESS);
}
#ifdef __amd64__
return (-1);
}
- sc->sc_proto = HV_VMBUS_VERSION_WS2008;
+ sc->sc_proto = VMBUS_VERSION_WS2008;
return (hv_init_synic(sc));
}
{
struct cpu_info *ci = curcpu();
int cpu = CPU_INFO_UNIT(ci);
- uint64_t simp, siefp, sctrl, sint, version;
+ uint64_t simp, siefp, sctrl, sint;
paddr_t pa;
- version = rdmsr(HV_X64_MSR_SVERSION);
-
/*
* Setup the Synic's message page
*/
printf(": SIMP PA extraction failed\n");
return (-1);
}
- simp = rdmsr(HV_X64_MSR_SIMP);
- simp &= (1 << HV_X64_MSR_SIMP_PASHIFT) - 1;
- simp |= (atop(pa) << HV_X64_MSR_SIMP_PASHIFT);
- simp |= HV_X64_MSR_SIMP_ENABLED;
- wrmsr(HV_X64_MSR_SIMP, simp);
+ simp = rdmsr(MSR_HV_SIMP);
+ simp &= (1 << MSR_HV_SIMP_PGSHIFT) - 1;
+ simp |= (atop(pa) << MSR_HV_SIMP_PGSHIFT);
+ simp |= MSR_HV_SIMP_ENABLE;
+ wrmsr(MSR_HV_SIMP, simp);
/*
* Setup the Synic's event page
printf(": SIEP PA extraction failed\n");
return (-1);
}
- siefp = rdmsr(HV_X64_MSR_SIEFP);
- siefp &= (1<<HV_X64_MSR_SIEFP_PASHIFT) - 1;
- siefp |= (atop(pa) << HV_X64_MSR_SIEFP_PASHIFT);
- siefp |= HV_X64_MSR_SIEFP_ENABLED;
- wrmsr(HV_X64_MSR_SIEFP, siefp);
+ siefp = rdmsr(MSR_HV_SIEFP);
+ siefp &= (1<<MSR_HV_SIEFP_PGSHIFT) - 1;
+ siefp |= (atop(pa) << MSR_HV_SIEFP_PGSHIFT);
+ siefp |= MSR_HV_SIEFP_ENABLE;
+ wrmsr(MSR_HV_SIEFP, siefp);
- /* HV_SHARED_SINT_IDT_VECTOR + 0x20 */
- sint = sc->sc_idtvec | HV_X64_MSR_SINT_AUTOEOI;
- wrmsr(HV_X64_MSR_SINT0 + HV_MESSAGE_SINT, sint);
+ /*
+ * Configure and unmask SINT for message and event flags
+ */
+ sint = rdmsr(MSR_HV_SINT0 + VMBUS_SINT_MESSAGE);
+ sint = sc->sc_idtvec | MSR_HV_SINT_AUTOEOI |
+ (sint & MSR_HV_SINT_RSVD_MASK);
+ wrmsr(MSR_HV_SINT0 + VMBUS_SINT_MESSAGE, sint);
/* Enable the global synic bit */
- sctrl = rdmsr(HV_X64_MSR_SCONTROL);
- sctrl |= HV_X64_MSR_SCONTROL_ENABLED;
- wrmsr(HV_X64_MSR_SCONTROL, sctrl);
+ sctrl = rdmsr(MSR_HV_SCONTROL);
+ sctrl |= MSR_HV_SCTRL_ENABLE;
+ wrmsr(MSR_HV_SCONTROL, sctrl);
- sc->sc_vcpus[cpu] = rdmsr(HV_X64_MSR_VP_INDEX);
+ sc->sc_vcpus[cpu] = rdmsr(MSR_HV_VP_INDEX);
DPRINTF("vcpu%u: SIMP %#llx SIEFP %#llx SCTRL %#llx\n",
sc->sc_vcpus[cpu], simp, siefp, sctrl);
struct hv_msg msg;
int rv;
- if (cmdlen > HV_MESSAGE_PAYLOAD) {
+ if (cmdlen > VMBUS_MSG_DSIZE_MAX) {
printf("%s: payload too large (%lu)\n", sc->sc_dev.dv_xname,
cmdlen);
return (EMSGSIZE);
memset(&msg, 0, sizeof(msg));
- msg.msg_req.payload_size = cmdlen;
- memcpy(msg.msg_req.payload, cmd, cmdlen);
+ msg.msg_req.hc_dsize = cmdlen;
+ memcpy(msg.msg_req.hc_data, cmd, cmdlen);
if (!(flags & HCF_NOREPLY)) {
msg.msg_rsp = rsp;
uint16_t status;
int i, s;
- msg->msg_req.connection_id = HV_MESSAGE_CONNECTION_ID;
- msg->msg_req.message_type = 1;
+ msg->msg_req.hc_connid = VMBUS_CONNID_MESSAGE;
+ msg->msg_req.hc_msgtype = 1;
if (!(msg->msg_flags & MSGF_NOQUEUE)) {
mtx_enter(&sc->sc_reqlck);
}
for (i = 0; i < nitems(delays); i++) {
- status = hv_hypercall(sc, HV_CALL_POST_MESSAGE,
+ status = hv_hypercall(sc, HYPERCALL_POST_MESSAGE,
&msg->msg_req, NULL);
- if (status != HV_STATUS_INSUFFICIENT_BUFFERS)
+ if (status == HYPERCALL_STATUS_SUCCESS)
break;
if (msg->msg_flags & MSGF_NOSLEEP) {
delay(delays[i]);
{
uint64_t status;
- status = hv_hypercall(sc, HV_CALL_SIGNAL_EVENT, con, NULL);
+ status = hv_hypercall(sc, HYPERCALL_SIGNAL_EVENT, con, NULL);
return ((uint16_t)status);
}
void
hv_event_intr(struct hv_softc *sc)
{
- struct hv_synic_event_flags *evt;
+ struct vmbus_evtflags *evt;
struct cpu_info *ci = curcpu();
int cpu = CPU_INFO_UNIT(ci);
- int bit, dword, maxdword, relid;
+ int bit, dword, maxdword, chanid;
struct hv_channel *ch;
uint32_t *revents, pending;
- evt = (struct hv_synic_event_flags *)sc->sc_siep[cpu] + HV_MESSAGE_SINT;
- if ((sc->sc_proto == HV_VMBUS_VERSION_WS2008) ||
- (sc->sc_proto == HV_VMBUS_VERSION_WIN7)) {
- if (atomic_clearbit_ptr(&evt->flags[0], 0) == 0)
+ evt = (struct vmbus_evtflags *)sc->sc_siep[cpu] +
+ VMBUS_SINT_MESSAGE;
+ if ((sc->sc_proto == VMBUS_VERSION_WS2008) ||
+ (sc->sc_proto == VMBUS_VERSION_WIN7)) {
+ if (atomic_clearbit_ptr(&evt->evt_flags[0], 0) == 0)
return;
- maxdword = HV_MAX_NUM_CHANNELS_SUPPORTED >> 5;
+ maxdword = VMBUS_CHAN_MAX_COMPAT >> 5;
/*
* receive size is 1/2 page and divide that by 4 bytes
*/
revents = sc->sc_revents;
} else {
- maxdword = nitems(evt->flags);
+ maxdword = nitems(evt->evt_flags);
/*
* On Host with Win8 or above, the event page can be
* checked directly to get the id of the channel
* that has the pending interrupt.
*/
- revents = &evt->flags[0];
+ revents = &evt->evt_flags[0];
}
for (dword = 0; dword < maxdword; dword++) {
for (bit = 0; pending > 0; pending >>= 1, bit++) {
if ((pending & 1) == 0)
continue;
- relid = (dword << 5) + bit;
+ chanid = (dword << 5) + bit;
/* vmbus channel protocol message */
- if (relid == 0)
+ if (chanid == 0)
continue;
- ch = hv_channel_lookup(sc, relid);
+ ch = hv_channel_lookup(sc, chanid);
if (ch == NULL) {
printf("%s: unhandled event on %d\n",
- sc->sc_dev.dv_xname, relid);
+ sc->sc_dev.dv_xname, chanid);
continue;
}
if (ch->ch_state != HV_CHANSTATE_OPENED) {
printf("%s: channel %d is not active\n",
- sc->sc_dev.dv_xname, relid);
+ sc->sc_dev.dv_xname, chanid);
continue;
}
ch->ch_evcnt.ec_count++;
void
hv_message_intr(struct hv_softc *sc)
{
- struct hv_vmbus_message *msg;
- struct hv_channel_msg_header *hdr;
+ struct vmbus_message *msg;
+ struct vmbus_chanmsg_hdr *hdr;
struct cpu_info *ci = curcpu();
int cpu = CPU_INFO_UNIT(ci);
for (;;) {
- msg = (struct hv_vmbus_message *)sc->sc_simp[cpu] +
- HV_MESSAGE_SINT;
- if (msg->header.message_type == HV_MESSAGE_TYPE_NONE)
+ msg = (struct vmbus_message *)sc->sc_simp[cpu] +
+ VMBUS_SINT_MESSAGE;
+ if (msg->msg_type == VMBUS_MSGTYPE_NONE)
break;
- hdr = (struct hv_channel_msg_header *)msg->payload;
- if (hdr->message_type >= HV_CHANMSG_COUNT) {
+ hdr = (struct vmbus_chanmsg_hdr *)msg->msg_data;
+ if (hdr->chm_type >= VMBUS_CHANMSG_COUNT) {
printf("%s: unhandled message type %u flags %#x\n",
- sc->sc_dev.dv_xname, hdr->message_type,
- msg->header.message_flags);
+ sc->sc_dev.dv_xname, hdr->chm_type,
+ msg->msg_flags);
goto skip;
}
- if (hv_msg_dispatch[hdr->message_type].hmd_handler)
- hv_msg_dispatch[hdr->message_type].hmd_handler(sc, hdr);
+ if (hv_msg_dispatch[hdr->chm_type].hmd_handler)
+ hv_msg_dispatch[hdr->chm_type].hmd_handler(sc, hdr);
else
printf("%s: unhandled message type %u\n",
- sc->sc_dev.dv_xname, hdr->message_type);
+ sc->sc_dev.dv_xname, hdr->chm_type);
skip:
- msg->header.message_type = HV_MESSAGE_TYPE_NONE;
+ msg->msg_type = VMBUS_MSGTYPE_NONE;
membar_sync();
- if (msg->header.message_flags & HV_SYNIC_MHF_PENDING)
- wrmsr(HV_X64_MSR_EOM, 0);
+ if (msg->msg_flags & VMBUS_MSGFLAG_PENDING)
+ wrmsr(MSR_HV_EOM, 0);
}
}
void
-hv_channel_response(struct hv_softc *sc, struct hv_channel_msg_header *rsphdr)
+hv_channel_response(struct hv_softc *sc, struct vmbus_chanmsg_hdr *rsphdr)
{
struct hv_msg *msg, *tmp;
- struct hv_channel_msg_header *reqhdr;
+ struct vmbus_chanmsg_hdr *reqhdr;
int req;
- req = hv_msg_dispatch[rsphdr->message_type].hmd_request;
+ req = hv_msg_dispatch[rsphdr->chm_type].hmd_request;
mtx_enter(&sc->sc_reqlck);
TAILQ_FOREACH_SAFE(msg, &sc->sc_reqs, msg_entry, tmp) {
- reqhdr = (struct hv_channel_msg_header *)&msg->msg_req.payload;
- if (reqhdr->message_type == req) {
+ reqhdr = (struct vmbus_chanmsg_hdr *)&msg->msg_req.hc_data;
+ if (reqhdr->chm_type == req) {
TAILQ_REMOVE(&sc->sc_reqs, msg, msg_entry);
break;
}
}
void
-hv_channel_offer(struct hv_softc *sc, struct hv_channel_msg_header *hdr)
+hv_channel_offer(struct hv_softc *sc, struct vmbus_chanmsg_hdr *hdr)
{
struct hv_offer *co;
}
void
-hv_channel_delivered(struct hv_softc *sc, struct hv_channel_msg_header *hdr)
+hv_channel_delivered(struct hv_softc *sc, struct vmbus_chanmsg_hdr *hdr)
{
atomic_setbits_int(&sc->sc_flags, HSF_OFFERS_DELIVERED);
wakeup(hdr);
int
hv_vmbus_connect(struct hv_softc *sc)
{
- const uint32_t versions[] = { HV_VMBUS_VERSION_WIN8_1,
- HV_VMBUS_VERSION_WIN8, HV_VMBUS_VERSION_WIN7,
- HV_VMBUS_VERSION_WS2008, HV_VMBUS_VERSION_INVALID
+ const uint32_t versions[] = {
+ VMBUS_VERSION_WIN8_1, VMBUS_VERSION_WIN8,
+ VMBUS_VERSION_WIN7, VMBUS_VERSION_WS2008
};
- struct hv_channel_initiate_contact cmd;
- struct hv_channel_version_response rsp;
+ struct vmbus_chanmsg_connect cmd;
+ struct vmbus_chanmsg_connect_resp rsp;
paddr_t epa, mpa1, mpa2;
int i;
}
memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.message_type = HV_CHANMSG_INITIATED_CONTACT;
- cmd.interrupt_page = (uint64_t)epa;
- cmd.monitor_page_1 = (uint64_t)mpa1;
- cmd.monitor_page_2 = (uint64_t)mpa2;
+ cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CONNECT;
+ cmd.chm_evtflags = (uint64_t)epa;
+ cmd.chm_mnf1 = (uint64_t)mpa1;
+ cmd.chm_mnf2 = (uint64_t)mpa2;
memset(&rsp, 0, sizeof(rsp));
- for (i = 0; versions[i] != HV_VMBUS_VERSION_INVALID; i++) {
- cmd.vmbus_version_requested = versions[i];
+ for (i = 0; i < nitems(versions); i++) {
+ cmd.chm_ver = versions[i];
if (hv_cmd(sc, &cmd, sizeof(cmd), &rsp, sizeof(rsp),
HCF_NOSLEEP)) {
- DPRINTF("%s: INITIATED_CONTACT failed\n",
+ DPRINTF("%s: CONNECT failed\n",
sc->sc_dev.dv_xname);
goto errout;
}
- if (rsp.version_supported) {
+ if (rsp.chm_done) {
sc->sc_flags |= HSF_CONNECTED;
sc->sc_proto = versions[i];
sc->sc_handle = 0xe1e10 - 1; /* magic! */
break;
}
}
- if (versions[i] == HV_VMBUS_VERSION_INVALID) {
+ if (i == nitems(versions)) {
printf("%s: failed to negotiate protocol version\n",
sc->sc_dev.dv_xname);
goto errout;
int
hv_channel_scan(struct hv_softc *sc)
{
- struct hv_channel_msg_header hdr;
- struct hv_channel_offer_channel rsp, *offer;
+ struct vmbus_chanmsg_hdr hdr;
+ struct vmbus_chanmsg_choffer rsp, *offer;
struct hv_offer *co;
SIMPLEQ_INIT(&sc->sc_offers);
mtx_init(&sc->sc_offerlck, IPL_NET);
- hdr.message_type = HV_CHANMSG_REQUEST_OFFERS;
- hdr.padding = 0;
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.chm_type = VMBUS_CHANMSG_CHREQUEST;
if (hv_cmd(sc, &hdr, sizeof(hdr), &rsp, sizeof(rsp), HCF_NOREPLY)) {
- DPRINTF("%s: REQUEST_OFFERS failed\n", sc->sc_dev.dv_xname);
+ DPRINTF("%s: CHREQUEST failed\n", sc->sc_dev.dv_xname);
return (-1);
}
return;
}
nch->ch_sc = sc;
- hv_guid_sprint(&co->co_chan.offer.interface_type, nch->ch_ident,
+ hv_guid_sprint(&co->co_chan.chm_chtype, nch->ch_ident,
sizeof(nch->ch_ident));
/*
*/
nch->ch_flags |= CHF_BATCHED;
- KASSERT((((vaddr_t)&nch->ch_sigevt) & 0x7) == 0);
- memset(&nch->ch_sigevt, 0, sizeof(nch->ch_sigevt));
- nch->ch_sigevt.connection_id = HV_EVENT_CONNECTION_ID;
+ KASSERT((((vaddr_t)&nch->ch_monprm) & 0x7) == 0);
+ memset(&nch->ch_monprm, 0, sizeof(nch->ch_monprm));
+ nch->ch_monprm.mp_connid = VMBUS_CONNID_EVENT;
- if (sc->sc_proto != HV_VMBUS_VERSION_WS2008) {
- if (co->co_chan.is_dedicated_interrupt)
- nch->ch_flags |= CHF_DEDICATED;
- nch->ch_sigevt.connection_id = co->co_chan.connection_id;
- }
+ if (sc->sc_proto != VMBUS_VERSION_WS2008)
+ nch->ch_monprm.mp_connid = co->co_chan.chm_connid;
- if (co->co_chan.monitor_allocated) {
- nch->ch_mgroup = co->co_chan.monitor_id >> 5;
- nch->ch_mindex = co->co_chan.monitor_id & 0x1f;
+ if (co->co_chan.chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) {
+ nch->ch_mgroup = co->co_chan.chm_montrig >> 5;
+ nch->ch_mindex = co->co_chan.chm_montrig & 0x1f;
nch->ch_flags |= CHF_MONITOR;
}
- nch->ch_relid = co->co_chan.child_rel_id;
+ nch->ch_id = co->co_chan.chm_chanid;
- memcpy(&nch->ch_type, &co->co_chan.offer.interface_type,
- sizeof(ch->ch_type));
- memcpy(&nch->ch_inst, &co->co_chan.offer.interface_instance,
- sizeof(ch->ch_inst));
+ memcpy(&nch->ch_type, &co->co_chan.chm_chtype, sizeof(ch->ch_type));
+ memcpy(&nch->ch_inst, &co->co_chan.chm_chinst, sizeof(ch->ch_inst));
mtx_enter(&sc->sc_channelck);
TAILQ_FOREACH(ch, &sc->sc_channels, ch_entry) {
break;
}
if (ch != NULL) {
- if (co->co_chan.offer.sub_channel_index == 0) {
+ if (co->co_chan.chm_subidx == 0) {
printf("%s: unknown offer \"%s\"\n",
sc->sc_dev.dv_xname, nch->ch_ident);
mtx_leave(&sc->sc_channelck);
}
#ifdef HYPERV_DEBUG
printf("%s: subchannel %u for \"%s\"\n", sc->sc_dev.dv_xname,
- co->co_chan.offer.sub_channel_index, ch->ch_ident);
+ co->co_chan.chm_subidx, ch->ch_ident);
#endif
mtx_leave(&sc->sc_channelck);
free(nch, M_DEVBUF, sizeof(*nch));
mtx_leave(&sc->sc_channelck);
#ifdef HYPERV_DEBUG
- printf("%s: channel %u: \"%s\"", sc->sc_dev.dv_xname, nch->ch_relid,
+ printf("%s: channel %u: \"%s\"", sc->sc_dev.dv_xname, nch->ch_id,
nch->ch_ident);
- if (co->co_chan.monitor_allocated)
- printf(", monitor %u\n", co->co_chan.monitor_id);
+ if (nch->ch_flags & CHF_MONITOR)
+ printf(", monitor %u\n", co->co_chan.chm_montrig);
else
printf("\n");
#endif
struct hv_channel *ch;
TAILQ_FOREACH(ch, &sc->sc_channels, ch_entry) {
- if (ch->ch_relid == relid)
+ if (ch->ch_id == relid)
return (ch);
}
return (NULL);
ch->ch_ring_npg = ch->ch_ring_size >> PAGE_SHIFT;
memset(&ch->ch_wrd, 0, sizeof(ch->ch_wrd));
- ch->ch_wrd.rd_ring = (struct hv_ring_buffer *)ch->ch_ring;
+ ch->ch_wrd.rd_ring = (struct vmbus_bufring *)ch->ch_ring;
ch->ch_wrd.rd_size = sndbuflen;
- ch->ch_wrd.rd_data_size = sndbuflen - sizeof(struct hv_ring_buffer);
+ ch->ch_wrd.rd_data_size = sndbuflen - sizeof(struct vmbus_bufring);
mtx_init(&ch->ch_wrd.rd_lock, IPL_NET);
memset(&ch->ch_rrd, 0, sizeof(ch->ch_rrd));
- ch->ch_rrd.rd_ring = (struct hv_ring_buffer *)((uint8_t *)ch->ch_ring +
+ ch->ch_rrd.rd_ring = (struct vmbus_bufring *)((uint8_t *)ch->ch_ring +
sndbuflen);
ch->ch_rrd.rd_size = rcvbuflen;
- ch->ch_rrd.rd_data_size = rcvbuflen - sizeof(struct hv_ring_buffer);
+ ch->ch_rrd.rd_data_size = rcvbuflen - sizeof(struct vmbus_bufring);
mtx_init(&ch->ch_rrd.rd_lock, IPL_NET);
if (hv_handle_alloc(ch, ch->ch_ring, sndbuflen + rcvbuflen,
- &ch->ch_ring_hndl)) {
+ &ch->ch_ring_gpadl)) {
printf("%s: failed to obtain a PA handle for the ring\n",
sc->sc_dev.dv_xname);
hv_channel_ring_destroy(ch);
km_free(ch->ch_ring, ch->ch_wrd.rd_size + ch->ch_rrd.rd_size,
&kv_any, &kp_zero);
ch->ch_ring = NULL;
- hv_handle_free(ch, ch->ch_ring_hndl);
+ hv_handle_free(ch, ch->ch_ring_gpadl);
memset(&ch->ch_wrd, 0, sizeof(ch->ch_wrd));
memset(&ch->ch_rrd, 0, sizeof(ch->ch_rrd));
void (*handler)(void *), void *arg)
{
struct hv_softc *sc = ch->ch_sc;
- struct hv_channel_open cmd;
- struct hv_channel_open_result rsp;
+ struct vmbus_chanmsg_chopen cmd;
+ struct vmbus_chanmsg_chopen_resp rsp;
int rv;
if (ch->ch_ring == NULL &&
}
memset(&cmd, 0, sizeof(cmd));
- cmd.header.message_type = HV_CHANMSG_OPEN_CHANNEL;
- cmd.open_id = ch->ch_relid;
- cmd.child_rel_id = ch->ch_relid;
- cmd.ring_buffer_gpadl_handle = ch->ch_ring_hndl;
- cmd.downstream_ring_buffer_page_offset =
- ch->ch_wrd.rd_size >> PAGE_SHIFT;
- cmd.target_vcpu = ch->ch_vcpu;
+ cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CHOPEN;
+ cmd.chm_openid = ch->ch_id;
+ cmd.chm_chanid = ch->ch_id;
+ cmd.chm_gpadl = ch->ch_ring_gpadl;
+ cmd.chm_txbr_pgcnt = ch->ch_wrd.rd_size >> PAGE_SHIFT;
+ cmd.chm_vcpuid = ch->ch_vcpu;
if (udata && udatalen > 0)
- memcpy(&cmd.user_data, udata, udatalen);
+ memcpy(cmd.chm_udata, udata, udatalen);
memset(&rsp, 0, sizeof(rsp));
rv = hv_cmd(sc, &cmd, sizeof(cmd), &rsp, sizeof(rsp), 0);
if (rv) {
hv_channel_ring_destroy(ch);
- DPRINTF("%s: OPEN_CHANNEL failed with %d\n",
+ DPRINTF("%s: CHOPEN failed with %d\n",
sc->sc_dev.dv_xname, rv);
ch->ch_handler = NULL;
ch->ch_ctx = NULL;
hv_channel_close(struct hv_channel *ch)
{
struct hv_softc *sc = ch->ch_sc;
- struct hv_channel_close cmd;
+ struct vmbus_chanmsg_chclose cmd;
int rv;
memset(&cmd, 0, sizeof(cmd));
- cmd.header.message_type = HV_CHANMSG_CLOSE_CHANNEL;
- cmd.child_rel_id = ch->ch_relid;
+ cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CHCLOSE;
+ cmd.chm_chanid = ch->ch_id;
ch->ch_state = HV_CHANSTATE_CLOSING;
rv = hv_cmd(sc, &cmd, sizeof(cmd), NULL, 0, HCF_NOREPLY);
if (rv) {
- DPRINTF("%s: CLOSE_CHANNEL failed with %d\n",
+ DPRINTF("%s: CHCLOSE failed with %d\n",
sc->sc_dev.dv_xname, rv);
return (-1);
}
static inline void
hv_channel_setevent(struct hv_softc *sc, struct hv_channel *ch)
{
- struct hv_monitor_trigger_group *mtg;
+ struct vmbus_mon_trig *mtg;
/* Each uint32_t represents 32 channels */
- atomic_setbit_ptr((uint32_t *)sc->sc_wevents + (ch->ch_relid >> 5),
- ch->ch_relid & 31);
+ atomic_setbit_ptr((uint32_t *)sc->sc_wevents + (ch->ch_id >> 5),
+ ch->ch_id & 31);
if (ch->ch_flags & CHF_MONITOR) {
- mtg = &sc->sc_monitor[1]->trigger_group[ch->ch_mgroup];
- atomic_setbit_ptr((uint32_t *)&mtg->pending, ch->ch_mindex);
+ mtg = &sc->sc_monitor[1]->mnf_trigs[ch->ch_mgroup];
+ atomic_setbit_ptr((uint32_t *)&mtg->mt_pending, ch->ch_mindex);
} else
- hv_intr_signal(sc, &ch->ch_sigevt);
+ hv_intr_signal(sc, &ch->ch_monprm);
}
static inline void
{
int left = MIN(datalen, wrd->rd_data_size - wrd->rd_prod);
- memcpy(&wrd->rd_ring->buffer[wrd->rd_prod], data, left);
- memcpy(&wrd->rd_ring->buffer[0], data + left, datalen - left);
+ memcpy(&wrd->rd_ring->br_data[wrd->rd_prod], data, left);
+ memcpy(&wrd->rd_ring->br_data[0], data + left, datalen - left);
wrd->rd_prod += datalen;
wrd->rd_prod %= wrd->rd_data_size;
}
{
int left = MIN(datalen, rrd->rd_data_size - rrd->rd_cons);
- memcpy(data, &rrd->rd_ring->buffer[rrd->rd_cons], left);
- memcpy(data + left, &rrd->rd_ring->buffer[0], datalen - left);
+ memcpy(data, &rrd->rd_ring->br_data[rrd->rd_cons], left);
+ memcpy(data + left, &rrd->rd_ring->br_data[0], datalen - left);
if (!peek) {
rrd->rd_cons += datalen;
rrd->rd_cons %= rrd->rd_data_size;
static inline void
hv_ring_avail(struct hv_ring_data *rd, uint32_t *towrite, uint32_t *toread)
{
- uint32_t ridx = rd->rd_ring->read_index;
- uint32_t widx = rd->rd_ring->write_index;
+ uint32_t ridx = rd->rd_ring->br_rindex;
+ uint32_t widx = rd->rd_ring->br_windex;
uint32_t r, w;
w = HV_BYTES_AVAIL_TO_WRITE(ridx, widx, rd->rd_data_size);
hv_ring_put(wrd, (uint8_t *)&indices, sizeof(indices));
membar_sync();
- wrd->rd_ring->write_index = wrd->rd_prod;
+ wrd->rd_ring->br_windex = wrd->rd_prod;
mtx_leave(&wrd->rd_lock);
/* Signal when the ring transitions from being empty to non-empty */
- if (wrd->rd_ring->interrupt_mask == 0 &&
- wrd->rd_ring->read_index == oprod)
+ if (wrd->rd_ring->br_imask == 0 &&
+ wrd->rd_ring->br_rindex == oprod)
*needsig = 1;
else
*needsig = 0;
uint64_t rid, int type, uint32_t flags)
{
struct hv_softc *sc = ch->ch_sc;
- struct hv_pktdesc d;
+ struct vmbus_chanpkt cp;
struct iovec iov[3];
uint32_t pktlen, pktlen_aligned;
uint64_t zeropad = 0;
int rv, needsig = 0;
- pktlen = sizeof(d) + datalen;
+ pktlen = sizeof(cp) + datalen;
pktlen_aligned = roundup(pktlen, sizeof(uint64_t));
- d.type = type;
- d.flags = flags;
- d.offset = sizeof(d) >> 3;
- d.length = pktlen_aligned >> 3;
- d.tid = rid;
+ cp.cp_hdr.cph_type = type;
+ cp.cp_hdr.cph_flags = flags;
+ VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_hlen, sizeof(cp));
+ VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_tlen, pktlen_aligned);
+ cp.cp_hdr.cph_tid = rid;
- iov[0].iov_base = &d;
- iov[0].iov_len = sizeof(d);
+ iov[0].iov_base = &cp;
+ iov[0].iov_len = sizeof(cp);
iov[1].iov_base = data;
iov[1].iov_len = datalen;
}
int
-hv_channel_sendbuf(struct hv_channel *ch, struct hv_page_buffer *pb,
- uint32_t npb, void *data, uint32_t datalen, uint64_t rid)
+hv_channel_send_sgl(struct hv_channel *ch, struct vmbus_gpa *sgl,
+ uint32_t nsge, void *data, uint32_t datalen, uint64_t rid)
{
struct hv_softc *sc = ch->ch_sc;
- struct hv_gpadesc d;
+ struct vmbus_chanpkt_sglist cp;
struct iovec iov[4];
uint32_t buflen, pktlen, pktlen_aligned;
uint64_t zeropad = 0;
int rv, needsig = 0;
- buflen = sizeof(struct hv_page_buffer) * npb;
- pktlen = sizeof(d) + datalen + buflen;
+ buflen = sizeof(struct vmbus_gpa) * nsge;
+ pktlen = sizeof(cp) + datalen + buflen;
pktlen_aligned = roundup(pktlen, sizeof(uint64_t));
- d.type = HV_PKT_DATA_USING_GPA_DIRECT;
- d.flags = HV_PKTFLAG_COMPLETION_REQUESTED;
- d.offset = (sizeof(d) + buflen) >> 3;
- d.length = pktlen_aligned >> 3;
- d.tid = rid;
- d.range_count = npb;
+ cp.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
+ cp.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
+ VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_hlen, sizeof(cp) + buflen);
+ VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_tlen, pktlen_aligned);
+ cp.cp_hdr.cph_tid = rid;
+ cp.cp_gpa_cnt = nsge;
- iov[0].iov_base = &d;
- iov[0].iov_len = sizeof(d);
+ iov[0].iov_base = &cp;
+ iov[0].iov_len = sizeof(cp);
- iov[1].iov_base = pb;
+ iov[1].iov_base = sgl;
iov[1].iov_len = buflen;
iov[2].iov_base = data;
hv_ring_get(rrd, (uint8_t *)&indices, sizeof(indices), 0);
membar_sync();
- rrd->rd_ring->read_index = rrd->rd_cons;
+ rrd->rd_ring->br_rindex = rrd->rd_cons;
mtx_leave(&rrd->rd_lock);
hv_channel_recv(struct hv_channel *ch, void *data, uint32_t datalen,
uint32_t *rlen, uint64_t *rid, int raw)
{
- struct hv_pktdesc d;
+ struct vmbus_chanpkt_hdr cph;
uint32_t offset, pktlen;
int rv;
*rlen = 0;
- if ((rv = hv_ring_peek(&ch->ch_rrd, &d, sizeof(d))) != 0)
+ if ((rv = hv_ring_peek(&ch->ch_rrd, &cph, sizeof(cph))) != 0)
return (rv);
- offset = raw ? 0 : (d.offset << 3);
- pktlen = (d.length << 3) - offset;
+ offset = raw ? 0 : VMBUS_CHANPKT_GETLEN(cph.cph_hlen);
+ pktlen = VMBUS_CHANPKT_GETLEN(cph.cph_tlen) - offset;
if (pktlen > datalen) {
printf("%s: pktlen %u datalen %u\n", __func__, pktlen, datalen);
return (EINVAL);
rv = hv_ring_read(&ch->ch_rrd, data, pktlen, offset);
if (rv == 0) {
*rlen = pktlen;
- *rid = d.tid;
+ *rid = cph.cph_tid;
}
return (rv);
uint32_t *handle)
{
struct hv_softc *sc = ch->ch_sc;
- struct hv_gpadl_header *hdr;
- struct hv_gpadl_body *body, *cmd;
- struct hv_gpadl_created rsp;
+ struct vmbus_chanmsg_gpadl_conn *hdr;
+ struct vmbus_chanmsg_gpadl_subconn *cmd;
+ struct vmbus_chanmsg_gpadl_connresp rsp;
struct hv_msg *msg;
int i, j, last, left, rv;
int bodylen = 0, ncmds = 0, pfn = 0;
int waitok = cold ? M_NOWAIT : M_WAITOK;
uint64_t *frames;
paddr_t pa;
+ caddr_t body;
/* Total number of pages to reference */
int total = atop(buflen);
/* Number of pages that will fit the header */
frames[i] = atop(pa);
}
- msg->msg_req.payload_size = sizeof(struct hv_gpadl_header) +
- sizeof(struct hv_gpa_range) + inhdr * sizeof(uint64_t);
- hdr = (struct hv_gpadl_header *)msg->msg_req.payload;
+ msg->msg_req.hc_dsize = sizeof(struct vmbus_chanmsg_gpadl_conn) +
+ /* sizeof(struct vmbus_gpa_range) */ + inhdr * sizeof(uint64_t);
+ hdr = (struct vmbus_chanmsg_gpadl_conn *)msg->msg_req.hc_data;
msg->msg_rsp = &rsp;
msg->msg_rsplen = sizeof(rsp);
if (!waitok)
/* Allocate additional gpadl_body structures if required */
if (left > 0) {
ncmds = MAX(1, left / HV_NPFNBODY + left % HV_NPFNBODY);
- bodylen = ncmds * HV_MESSAGE_PAYLOAD;
+ bodylen = ncmds * VMBUS_MSG_DSIZE_MAX;
body = malloc(bodylen, M_DEVBUF, M_ZERO | waitok);
if (body == NULL) {
free(msg, M_DEVBUF, sizeof(*msg));
*handle = atomic_inc_int_nv(&sc->sc_handle);
- hdr->header.message_type = HV_CHANMSG_GPADL_HEADER;
- hdr->child_rel_id = ch->ch_relid;
- hdr->gpadl = *handle;
+ hdr->chm_hdr.chm_type = VMBUS_CHANMSG_GPADL_CONN;
+ hdr->chm_chanid = ch->ch_id;
+ hdr->chm_gpadl = *handle;
/* Single range for a contiguous buffer */
- hdr->range_count = 1;
- hdr->range_buf_len = sizeof(struct hv_gpa_range) + total *
+ hdr->chm_range_cnt = 1;
+ hdr->chm_range_len = sizeof(struct vmbus_gpa_range) + total *
sizeof(uint64_t);
- hdr->range[0].byte_offset = 0;
- hdr->range[0].byte_count = buflen;
+ hdr->chm_range.gpa_ofs = 0;
+ hdr->chm_range.gpa_len = buflen;
/* Fit as many pages as possible into the header */
for (i = 0; i < inhdr; i++)
- hdr->range[0].pfn_array[i] = frames[pfn++];
+ hdr->chm_range.gpa_page[i] = frames[pfn++];
for (i = 0; i < ncmds; i++) {
- cmd = (struct hv_gpadl_body *)((caddr_t)body +
- HV_MESSAGE_PAYLOAD * i);
- cmd->header.message_type = HV_CHANMSG_GPADL_BODY;
- cmd->gpadl = *handle;
+ cmd = (struct vmbus_chanmsg_gpadl_subconn *)(body +
+ VMBUS_MSG_DSIZE_MAX * i);
+ cmd->chm_hdr.chm_type = VMBUS_CHANMSG_GPADL_SUBCONN;
+ cmd->chm_gpadl = *handle;
last = MIN(left, HV_NPFNBODY);
for (j = 0; j < last; j++)
- cmd->pfn[j] = frames[pfn++];
+ cmd->chm_gpa_page[j] = frames[pfn++];
left -= last;
}
rv = hv_start(sc, msg);
if (rv != 0) {
- DPRINTF("%s: GPADL_HEADER failed\n", sc->sc_dev.dv_xname);
+ DPRINTF("%s: GPADL_CONN failed\n", sc->sc_dev.dv_xname);
goto out;
}
for (i = 0; i < ncmds; i++) {
int cmdlen = sizeof(*cmd);
- cmd = (struct hv_gpadl_body *)((caddr_t)body +
- HV_MESSAGE_PAYLOAD * i);
+ cmd = (struct vmbus_chanmsg_gpadl_subconn *)(body +
+ VMBUS_MSG_DSIZE_MAX * i);
/* Last element can be short */
if (i == ncmds - 1)
cmdlen += last * sizeof(uint64_t);
cmdlen += HV_NPFNBODY * sizeof(uint64_t);
rv = hv_cmd(sc, cmd, cmdlen, NULL, 0, waitok | HCF_NOREPLY);
if (rv != 0) {
- DPRINTF("%s: GPADL_BODY (iteration %d/%d) failed "
+ DPRINTF("%s: GPADL_SUBCONN (iteration %d/%d) failed "
"with %d\n", sc->sc_dev.dv_xname, i, ncmds, rv);
goto out;
}
if (rv != 0)
return (rv);
- KASSERT(*handle == rsp.gpadl);
+ KASSERT(*handle == rsp.chm_gpadl);
return (0);
}
hv_handle_free(struct hv_channel *ch, uint32_t handle)
{
struct hv_softc *sc = ch->ch_sc;
- struct hv_gpadl_teardown cmd;
- struct hv_gpadl_torndown rsp;
+ struct vmbus_chanmsg_gpadl_disconn cmd;
+ struct vmbus_chanmsg_gpadl_disconn rsp;
int rv;
memset(&cmd, 0, sizeof(cmd));
- cmd.header.message_type = HV_CHANMSG_GPADL_TEARDOWN;
- cmd.child_rel_id = ch->ch_relid;
- cmd.gpadl = handle;
+ cmd.chm_hdr.chm_type = VMBUS_CHANMSG_GPADL_DISCONN;
+ cmd.chm_chanid = ch->ch_id;
+ cmd.chm_gpadl = handle;
rv = hv_cmd(sc, &cmd, sizeof(cmd), &rsp, sizeof(rsp), 0);
if (rv)
- DPRINTF("%s: GPADL_TEARDOWN failed with %d\n",
+ DPRINTF("%s: GPADL_DISCONN failed with %d\n",
sc->sc_dev.dv_xname, rv);
}
sc->sc_dev.dv_xname, hdr->icmsgtype);
}
hdr->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
- hv_channel_send(ch, ch->ch_buf, rlen, rid, HV_PKT_DATA_IN_BAND, 0);
+ hv_channel_send(ch, ch->ch_buf, rlen, rid, VMBUS_CHANPKT_TYPE_INBAND, 0);
}
void
msg = (struct hv_shutdown_msg *)(hdr + 1);
if (msg->flags == 0 || msg->flags == 1) {
shutdown = 1;
- hdr->status = HV_S_OK;
+ hdr->status = HV_ICMSG_STATUS_OK;
} else
- hdr->status = HV_E_FAIL;
+ hdr->status = HV_ICMSG_STATUS_FAIL;
} else if (hdr->icmsgtype != HV_ICMSGTYPE_NEGOTIATE) {
printf("%s: unhandled shutdown message type %u\n",
sc->sc_dev.dv_xname, hdr->icmsgtype);
}
hdr->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
- hv_channel_send(ch, ch->ch_buf, rlen, rid, HV_PKT_DATA_IN_BAND, 0);
+ hv_channel_send(ch, ch->ch_buf, rlen, rid, VMBUS_CHANPKT_TYPE_INBAND, 0);
if (shutdown)
task_add(systq, &sc->sc_sdtask);
}
hdr->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
- hv_channel_send(ch, ch->ch_buf, rlen, rid, HV_PKT_DATA_IN_BAND, 0);
+ hv_channel_send(ch, ch->ch_buf, rlen, rid, VMBUS_CHANPKT_TYPE_INBAND, 0);
}
static int
/*-
- * Copyright (c) 2009-2012 Microsoft Corp.
+ * Copyright (c) 2009-2012,2016 Microsoft Corp.
* Copyright (c) 2012 NetApp Inc.
* Copyright (c) 2012 Citrix Inc.
* All rights reserved.
#ifndef _HYPERVREG_H_
#define _HYPERVREG_H_
+struct hv_guid {
+ unsigned char data[16];
+} __packed;
+
+#define VMBUS_CONNID_MESSAGE 1
+#define VMBUS_CONNID_EVENT 2
+#define VMBUS_SINT_MESSAGE 2
+
+/* =============================================================================
+ * hyperv_reg.h
+ * =============================================================================
+ */
+
+/*
+ * Hyper-V Synthetic MSRs
+ */
+
+#define MSR_HV_GUEST_OS_ID 0x40000000
+#define MSR_HV_GUESTID_BUILD_MASK 0xffffULL
+#define MSR_HV_GUESTID_VERSION_MASK 0x0000ffffffff0000ULL
+#define MSR_HV_GUESTID_VERSION_SHIFT 16
+#define MSR_HV_GUESTID_OSID_MASK 0x00ff000000000000ULL
+#define MSR_HV_GUESTID_OSID_SHIFT 48
+#define MSR_HV_GUESTID_OSTYPE_MASK 0x7f00000000000000ULL
+#define MSR_HV_GUESTID_OSTYPE_SHIFT 56
+#define MSR_HV_GUESTID_OPENSRC 0x8000000000000000ULL
+#define MSR_HV_GUESTID_OSTYPE_LINUX \
+ ((0x01ULL << MSR_HV_GUESTID_OSTYPE_SHIFT) | MSR_HV_GUESTID_OPENSRC)
+#define MSR_HV_GUESTID_OSTYPE_FREEBSD \
+ ((0x02ULL << MSR_HV_GUESTID_OSTYPE_SHIFT) | MSR_HV_GUESTID_OPENSRC)
+
+#define MSR_HV_HYPERCALL 0x40000001
+#define MSR_HV_HYPERCALL_ENABLE 0x0001ULL
+#define MSR_HV_HYPERCALL_RSVD_MASK 0x0ffeULL
+#define MSR_HV_HYPERCALL_PGSHIFT 12
+
+#define MSR_HV_VP_INDEX 0x40000002
+
+#define MSR_HV_TIME_REF_COUNT 0x40000020
+
+#define MSR_HV_SCONTROL 0x40000080
+#define MSR_HV_SCTRL_ENABLE 0x0001ULL
+#define MSR_HV_SCTRL_RSVD_MASK 0xfffffffffffffffeULL
+
+#define MSR_HV_SIEFP 0x40000082
+#define MSR_HV_SIEFP_ENABLE 0x0001ULL
+#define MSR_HV_SIEFP_RSVD_MASK 0x0ffeULL
+#define MSR_HV_SIEFP_PGSHIFT 12
+
+#define MSR_HV_SIMP 0x40000083
+#define MSR_HV_SIMP_ENABLE 0x0001ULL
+#define MSR_HV_SIMP_RSVD_MASK 0x0ffeULL
+#define MSR_HV_SIMP_PGSHIFT 12
+
+#define MSR_HV_EOM 0x40000084
+
+#define MSR_HV_SINT0 0x40000090
+#define MSR_HV_SINT_VECTOR_MASK 0x00ffULL
+#define MSR_HV_SINT_RSVD1_MASK 0xff00ULL
+#define MSR_HV_SINT_MASKED 0x00010000ULL
+#define MSR_HV_SINT_AUTOEOI 0x00020000ULL
+#define MSR_HV_SINT_RSVD2_MASK 0xfffffffffffc0000ULL
+#define MSR_HV_SINT_RSVD_MASK (MSR_HV_SINT_RSVD1_MASK | \
+ MSR_HV_SINT_RSVD2_MASK)
+
+#define MSR_HV_STIMER0_CONFIG 0x400000b0
+#define MSR_HV_STIMER_CFG_ENABLE 0x0001ULL
+#define MSR_HV_STIMER_CFG_PERIODIC 0x0002ULL
+#define MSR_HV_STIMER_CFG_LAZY 0x0004ULL
+#define MSR_HV_STIMER_CFG_AUTOEN 0x0008ULL
+#define MSR_HV_STIMER_CFG_SINT_MASK 0x000f0000ULL
+#define MSR_HV_STIMER_CFG_SINT_SHIFT 16
+
+#define MSR_HV_STIMER0_COUNT 0x400000b1
+
+/*
+ * CPUID leaves
+ */
+
+#define CPUID_LEAF_HV_MAXLEAF 0x40000000
+
+#define CPUID_LEAF_HV_INTERFACE 0x40000001
+#define CPUID_HV_IFACE_HYPERV 0x31237648 /* HV#1 */
+
+#define CPUID_LEAF_HV_IDENTITY 0x40000002
+
+#define CPUID_LEAF_HV_FEATURES 0x40000003
+/* EAX: features */
+#define CPUID_HV_MSR_TIME_REFCNT 0x0002 /* MSR_HV_TIME_REF_COUNT */
+#define CPUID_HV_MSR_SYNIC 0x0004 /* MSRs for SynIC */
+#define CPUID_HV_MSR_SYNTIMER 0x0008 /* MSRs for SynTimer */
+#define CPUID_HV_MSR_APIC 0x0010 /* MSR_HV_{EOI,ICR,TPR} */
+#define CPUID_HV_MSR_HYPERCALL 0x0020 /* MSR_HV_GUEST_OS_ID
+ * MSR_HV_HYPERCALL */
+#define CPUID_HV_MSR_VP_INDEX 0x0040 /* MSR_HV_VP_INDEX */
+#define CPUID_HV_MSR_GUEST_IDLE 0x0400 /* MSR_HV_GUEST_IDLE */
+/* ECX: power management features */
+#define CPUPM_HV_CSTATE_MASK 0x000f /* deepest C-state */
+#define CPUPM_HV_C3_HPET 0x0010 /* C3 requires HPET */
+#define CPUPM_HV_CSTATE(f) ((f) & CPUPM_HV_CSTATE_MASK)
+/* EDX: features3 */
+#define CPUID3_HV_MWAIT 0x0001 /* MWAIT */
+#define CPUID3_HV_XMM_HYPERCALL 0x0010 /* Hypercall input through
+ * XMM regs */
+#define CPUID3_HV_GUEST_IDLE 0x0020 /* guest idle */
+#define CPUID3_HV_NUMA 0x0080 /* NUMA distance query */
+#define CPUID3_HV_TIME_FREQ 0x0100 /* timer frequency query
+ * (TSC, LAPIC) */
+#define CPUID3_HV_MSR_CRASH 0x0400 /* MSRs for guest crash */
+
+#define CPUID_LEAF_HV_RECOMMENDS 0x40000004
+#define CPUID_LEAF_HV_LIMITS 0x40000005
+#define CPUID_LEAF_HV_HWFEATURES 0x40000006
+
+/*
+ * Hyper-V Monitor Notification Facility
+ */
+struct hv_mon_param {
+ uint32_t mp_connid;
+ uint16_t mp_evtflag_ofs;
+ uint16_t mp_rsvd;
+} __packed;
+
+/*
+ * Hyper-V message types
+ */
+#define VMBUS_MSGTYPE_NONE 0
+#define VMBUS_MSGTYPE_CHANNEL 1
+#define VMBUS_MSGTYPE_TIMER_EXPIRED 0x80000010
+
+/*
+ * Hypercall status codes
+ */
+#define HYPERCALL_STATUS_SUCCESS 0x0000
+
+/*
+ * Hypercall input values
+ */
+#define HYPERCALL_POST_MESSAGE 0x005c
+#define HYPERCALL_SIGNAL_EVENT 0x005d
+
/*
- * hyperv.h
+ * Hypercall input parameters
+ */
+#define HYPERCALL_PARAM_ALIGN 8
+#if 0
+/*
+ * XXX
+ * <<Hypervisor Top Level Functional Specification 4.0b>> requires
+ * input parameters size to be multiple of 8, however, many post
+ * message input parameters do _not_ meet this requirement.
+ */
+#define HYPERCALL_PARAM_SIZE_ALIGN 8
+#endif
+
+/*
+ * HYPERCALL_POST_MESSAGE
+ */
+#define HYPERCALL_POSTMSGIN_DSIZE_MAX 240
+#define HYPERCALL_POSTMSGIN_SIZE 256
+
+struct hypercall_postmsg_in {
+ uint32_t hc_connid;
+ uint32_t hc_rsvd;
+ uint32_t hc_msgtype; /* VMBUS_MSGTYPE_ */
+ uint32_t hc_dsize;
+ uint8_t hc_data[HYPERCALL_POSTMSGIN_DSIZE_MAX];
+} __packed;
+
+/*
+ * =============================================================================
+ * vmbus.h
+ * =============================================================================
*/
/*
* 2.4 -- Windows 8
* 3.0 -- Windows 8.1
*/
-#define HV_VMBUS_VERSION_WS2008 ((0 << 16) | (13))
-#define HV_VMBUS_VERSION_WIN7 ((1 << 16) | (1))
-#define HV_VMBUS_VERSION_WIN8 ((2 << 16) | (4))
-#define HV_VMBUS_VERSION_WIN8_1 ((3 << 16) | (0))
-#define HV_VMBUS_VERSION_INVALID -1
-#define HV_VMBUS_VERSION_CURRENT HV_VMBUS_VERSION_WIN8_1
+#define VMBUS_VERSION_WS2008 ((0 << 16) | (13))
+#define VMBUS_VERSION_WIN7 ((1 << 16) | (1))
+#define VMBUS_VERSION_WIN8 ((2 << 16) | (4))
+#define VMBUS_VERSION_WIN8_1 ((3 << 16) | (0))
-#define HV_CONNECTION_ID_MASK 0x1ffffff
+#define VMBUS_VERSION_MAJOR(ver) (((uint32_t)(ver)) >> 16)
+#define VMBUS_VERSION_MINOR(ver) (((uint32_t)(ver)) & 0xffff)
-/* Pipe modes */
-#define HV_PIPE_TYPE_BYTE 0x00000000
-#define HV_PIPE_TYPE_MESSAGE 0x00000004
+/*
+ * GPA stuffs.
+ */
+struct vmbus_gpa_range {
+ uint32_t gpa_len;
+ uint32_t gpa_ofs;
+ uint64_t gpa_page[0];
+} __packed;
-/* The size of the user defined data buffer for non-pipe offers */
-#define HV_MAX_USER_BYTES 120
+/* This is actually vmbus_gpa_range.gpa_page[1] */
+struct vmbus_gpa {
+ uint32_t gpa_len;
+ uint32_t gpa_ofs;
+ uint64_t gpa_page;
+} __packed;
-/* The size of the user defined data buffer for pipe offers */
-#define HV_MAX_PIPE_USER_BYTES 116
+#define VMBUS_CHANPKT_SIZE_SHIFT 3
-struct hv_guid {
- unsigned char data[16];
+#define VMBUS_CHANPKT_GETLEN(pktlen) \
+ (((int)(pktlen)) << VMBUS_CHANPKT_SIZE_SHIFT)
+
+struct vmbus_chanpkt_hdr {
+ uint16_t cph_type; /* VMBUS_CHANPKT_TYPE_ */
+ uint16_t cph_hlen; /* header len, in 8 bytes */
+ uint16_t cph_tlen; /* total len, in 8 bytes */
+ uint16_t cph_flags; /* VMBUS_CHANPKT_FLAG_ */
+ uint64_t cph_tid;
} __packed;
-/*
- * This struct contains the fundamental information about an offer.
- */
-struct hv_channel_offer {
- struct hv_guid interface_type;
- struct hv_guid interface_instance;
- uint64_t interrupt_latency_in_100ns_units;
- uint32_t interface_revision;
- uint32_t server_context_area_size; /* in bytes */
- uint16_t channel_flags;
- uint16_t mmio_megabytes; /* bytes * 1024*1024 */
- union {
- /*
- * Non-pipes: The user has HV_MAX_USER_BYTES bytes.
- */
- struct {
- uint8_t user_defined[HV_MAX_USER_BYTES];
- } __packed standard;
-
- /*
- * Pipes: The following structure is an integrated pipe
- * protocol, which is implemented on top of standard user-
- * defined data. pipe clients have HV_MAX_PIPE_USER_BYTES
- * left for their own use.
- */
- struct {
- uint32_t pipe_mode;
- uint8_t user_defined[HV_MAX_PIPE_USER_BYTES];
- } __packed pipe;
- } u;
+#define VMBUS_CHANPKT_TYPE_INBAND 0x0006
+#define VMBUS_CHANPKT_TYPE_RXBUF 0x0007
+#define VMBUS_CHANPKT_TYPE_GPA 0x0009
+#define VMBUS_CHANPKT_TYPE_COMP 0x000b
- /*
- * Sub_channel_index, newly added in Win8.
- */
- uint16_t sub_channel_index;
- uint16_t padding;
-} __packed;
+#define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */
-struct hv_pktdesc {
- uint16_t type;
- uint16_t offset;
- uint16_t length;
- uint16_t flags;
- uint64_t tid;
-} __packed;
+#define VMBUS_CHANPKT_CONST_DATA(pkt) \
+ ((const void *)((const uint8_t *)(pkt) + \
+ VMBUS_CHANPKT_GETLEN((pkt)->cph_hlen)))
-struct hv_transfer_page {
- uint32_t byte_count;
- uint32_t byte_offset;
+struct vmbus_rxbuf_desc {
+ uint32_t rb_len;
+ uint32_t rb_ofs;
} __packed;
-struct hv_transfer_page_header {
- uint16_t set_id;
- uint8_t sender_owns_set;
- uint8_t reserved;
- uint32_t range_count;
- struct hv_transfer_page range[0];
+struct vmbus_chanpkt_rxbuf {
+ struct vmbus_chanpkt_hdr cp_hdr;
+ uint16_t cp_rxbuf_id;
+ uint16_t cp_rsvd;
+ uint32_t cp_rxbuf_cnt;
+ struct vmbus_rxbuf_desc cp_rxbuf[0];
} __packed;
/*
- * This structure defines a range in guest physical space that
- * can be made to look virtually contiguous.
+ * =============================================================================
+ * vmbus_reg.h
+ * =============================================================================
*/
-struct hv_gpa_range {
- uint32_t byte_count;
- uint32_t byte_offset;
- uint64_t pfn_array[0];
-} __packed;
-
-#define HV_PKT_INVALID 0x0
-#define HV_PKT_SYNCH 0x1
-#define HV_PKT_ADD_TRANSFER_PAGE_SET 0x2
-#define HV_PKT_REMOVE_TRANSFER_PAGE_SET 0x3
-#define HV_PKT_ESTABLISH_GPADL 0x4
-#define HV_PKT_TEAR_DOWN_GPADL 0x5
-#define HV_PKT_DATA_IN_BAND 0x6
-#define HV_PKT_DATA_USING_TRANSFER_PAGES 0x7
-#define HV_PKT_DATA_USING_GPADL 0x8
-#define HV_PKT_DATA_USING_GPA_DIRECT 0x9
-#define HV_PKT_CANCEL_REQUEST 0xa
-#define HV_PKT_COMPLETION 0xb
-#define HV_PKT_DATA_USING_ADDITIONAL_PACKETS 0xc
-#define HV_PKT_ADDITIONAL_DATA 0xd
-
-#define HV_PKTFLAG_COMPLETION_REQUESTED 1
-
-#define HV_CHANMSG_INVALID 0
-#define HV_CHANMSG_OFFER_CHANNEL 1
-#define HV_CHANMSG_RESCIND_CHANNEL_OFFER 2
-#define HV_CHANMSG_REQUEST_OFFERS 3
-#define HV_CHANMSG_ALL_OFFERS_DELIVERED 4
-#define HV_CHANMSG_OPEN_CHANNEL 5
-#define HV_CHANMSG_OPEN_CHANNEL_RESULT 6
-#define HV_CHANMSG_CLOSE_CHANNEL 7
-#define HV_CHANMSG_GPADL_HEADER 8
-#define HV_CHANMSG_GPADL_BODY 9
-#define HV_CHANMSG_GPADL_CREATED 10
-#define HV_CHANMSG_GPADL_TEARDOWN 11
-#define HV_CHANMSG_GPADL_TORNDOWN 12
-#define HV_CHANMSG_REL_ID_RELEASED 13
-#define HV_CHANMSG_INITIATED_CONTACT 14
-#define HV_CHANMSG_VERSION_RESPONSE 15
-#define HV_CHANMSG_UNLOAD 16
-#define HV_CHANMSG_COUNT 17
-
-struct hv_channel_msg_header {
- uint32_t message_type;
- uint32_t padding;
-} __packed;
-
-struct hv_channel_initiate_contact {
- struct hv_channel_msg_header hdr;
- uint32_t vmbus_version_requested;
- uint32_t padding2;
- uint64_t interrupt_page;
- uint64_t monitor_page_1;
- uint64_t monitor_page_2;
-} __packed;
-
-struct hv_channel_version_response {
- struct hv_channel_msg_header header;
- uint8_t version_supported;
-} __packed;
/*
- * Common defines for Hyper-V ICs
+ * Hyper-V SynIC message format.
*/
-#define HV_ICMSGTYPE_NEGOTIATE 0
-#define HV_ICMSGTYPE_HEARTBEAT 1
-#define HV_ICMSGTYPE_KVPEXCHANGE 2
-#define HV_ICMSGTYPE_SHUTDOWN 3
-#define HV_ICMSGTYPE_TIMESYNC 4
-#define HV_ICMSGTYPE_VSS 5
-#define HV_ICMSGHDRFLAG_TRANSACTION 1
-#define HV_ICMSGHDRFLAG_REQUEST 2
-#define HV_ICMSGHDRFLAG_RESPONSE 4
+#define VMBUS_MSG_DSIZE_MAX 240
+#define VMBUS_MSG_SIZE 256
-struct hv_pipe_hdr {
- uint32_t flags;
- uint32_t msgsize;
+struct vmbus_message {
+ uint32_t msg_type; /* VMBUS_MSGTYPE_ */
+ uint8_t msg_dsize; /* data size */
+ uint8_t msg_flags; /* VMBUS_MSGFLAG_ */
+ uint16_t msg_rsvd;
+ uint64_t msg_id;
+ uint8_t msg_data[VMBUS_MSG_DSIZE_MAX];
} __packed;
-struct hv_ic_version {
- uint16_t major;
- uint16_t minor;
-} __packed;
+#define VMBUS_MSGFLAG_PENDING 0x01
-struct hv_icmsg_hdr {
- struct hv_ic_version icverframe;
- uint16_t icmsgtype;
- struct hv_ic_version icvermsg;
- uint16_t icmsgsize;
- uint32_t status;
- uint8_t ictransaction_id;
- uint8_t icflags;
- uint8_t reserved[2];
-} __packed;
+/*
+ * Hyper-V SynIC event flags
+ */
-struct hv_icmsg_negotiate {
- uint16_t icframe_vercnt;
- uint16_t icmsg_vercnt;
- uint32_t reserved;
- struct hv_ic_version icversion_data[1]; /* any size array */
+struct vmbus_evtflags {
+ uint32_t evt_flags[64];
} __packed;
-struct hv_shutdown_msg {
- uint32_t reason_code;
- uint32_t timeout_seconds;
- uint32_t flags;
- uint8_t display_message[2048];
-} __packed;
+/*
+ * Hyper-V Monitor Notification Facility
+ */
-struct hv_timesync_msg {
- uint64_t parent_time;
- uint64_t child_time;
- uint64_t round_trip_time;
- uint8_t flags;
-#define HV_TIMESYNC_PROBE 0
-#define HV_TIMESYNC_SYNC 1
-#define HV_TIMESYNC_SAMPLE 2
+struct vmbus_mon_trig {
+ uint32_t mt_pending;
+ uint32_t mt_armed;
} __packed;
-struct hv_heartbeat_msg {
- uint64_t seq_num;
- uint32_t reserved[8];
-} __packed;
+#define VMBUS_MONTRIGS_MAX 4
+#define VMBUS_MONTRIG_LEN 32
-struct hv_ring_buffer {
- /* Offset in bytes from the start of ring data below */
- volatile uint32_t write_index;
- /* Offset in bytes from the start of ring data below */
- volatile uint32_t read_index;
- /* Interrupt mask */
- volatile uint32_t interrupt_mask;
- /* Ring data starts on the next page */
- uint8_t reserved[4084];
- /* Data, doubles as interrupt mask */
- uint8_t buffer[0];
-} __packed;
+struct vmbus_mnf {
+ uint32_t mnf_state;
+ uint32_t mnf_rsvd1;
-struct hv_page_buffer {
- int length;
- int offset;
- uint64_t pfn;
-} __packed;
+ struct vmbus_mon_trig
+ mnf_trigs[VMBUS_MONTRIGS_MAX];
+ uint8_t mnf_rsvd2[536];
-#define HV_MAX_PAGE_BUFFERS 32
+ uint16_t mnf_lat[VMBUS_MONTRIGS_MAX][VMBUS_MONTRIG_LEN];
+ uint8_t mnf_rsvd3[256];
-struct hv_gpadesc {
- uint16_t type;
- uint16_t offset;
- uint16_t length;
- uint16_t flags;
- uint64_t tid;
- uint32_t reserved;
- uint32_t range_count;
+ struct hv_mon_param
+ mnf_param[VMBUS_MONTRIGS_MAX][VMBUS_MONTRIG_LEN];
+ uint8_t mnf_rsvd4[1984];
} __packed;
/*
- * Channel Offer parameters
+ * Buffer ring
*/
-struct hv_channel_offer_channel {
- struct hv_channel_msg_header header;
- struct hv_channel_offer offer;
- uint32_t child_rel_id;
- uint8_t monitor_id;
+struct vmbus_bufring {
/*
- * This field has been split into a bit field on Win7 and higher.
+ * If br_windex == br_rindex, this bufring is empty; this
+ * means we can _not_ write data to the bufring, if the
+ * write is going to make br_windex same as br_rindex.
*/
- uint8_t monitor_allocated:1;
- uint8_t reserved1:7;
+ volatile uint32_t br_windex;
+ volatile uint32_t br_rindex;
+
/*
- * Following fields were added in win7 and higher.
- * Make sure to check the version before accessing these fields.
+ * Interrupt mask {0,1}
*
- * If "is_dedicated_interrupt" is set, we must not set the
- * associated bit in the channel bitmap while sending the
- * interrupt to the host.
+ * For TX bufring, host set this to 1, when it is processing
+ * the TX bufring, so that we can safely skip the TX event
+ * notification to host.
*
- * connection_id is used in signaling the host.
+ * For RX bufring, once this is set to 1 by us, host will not
+ * further dispatch interrupts to us, even if there are data
+ * pending on the RX bufring. This effectively disables the
+ * interrupt of the channel to which this RX bufring is attached.
*/
- uint16_t is_dedicated_interrupt:1;
- uint16_t reserved2:15;
- uint32_t connection_id;
-} __packed;
+ volatile uint32_t br_imask;
-/*
- * Open Channel parameters
- */
-struct hv_channel_open {
- struct hv_channel_msg_header header;
- /* Identifies the specific VMBus channel that is being opened */
- uint32_t child_rel_id;
- /* ID making a particular open request at a channel offer unique */
- uint32_t open_id;
- /* GPADL for the channel's ring buffer */
- uint32_t ring_buffer_gpadl_handle;
- /*
- * Before win8, all incoming channel interrupts are only delivered
- * on cpu 0. Setting this value to 0 would preserve the earlier
- * behavior.
- */
- uint32_t target_vcpu;
- /*
- * The upstream ring buffer begins at offset zero in the memory
- * described by ring_buffer_gpadl_handle. The downstream ring
- * buffer follows it at this offset (in pages).
- */
- uint32_t downstream_ring_buffer_page_offset;
- /* User-specific data to be passed along to the server endpoint. */
- uint8_t user_data[HV_MAX_USER_BYTES];
+ uint8_t br_rsvd[4084];
+ uint8_t br_data[0];
} __packed;
/*
- * Open Channel Result parameters
+ * Channel
*/
-struct hv_channel_open_result {
- struct hv_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t open_id;
- uint32_t status;
-} __packed;
-/*
- * Close channel parameters
- */
-struct hv_channel_close {
- struct hv_channel_msg_header header;
- uint32_t child_rel_id;
-} __packed;
+#define VMBUS_CHAN_MAX_COMPAT 256
+#define VMBUS_CHAN_MAX (VMBUS_EVTFLAG_LEN * VMBUS_EVTFLAGS_MAX)
/*
- * Channel Message GPADL
+ * Channel packets
*/
-#define HV_GPADL_TYPE_RING_BUFFER 1
-#define HV_GPADL_TYPE_SERVER_SAVE_AREA 2
-#define HV_GPADL_TYPE_TRANSACTION 8
-/*
- * The number of PFNs in a GPADL message is defined by the number of
- * pages that would be spanned by byte_count and byte_offset. If the
- * implied number of PFNs won't fit in this packet, there will be a
- * follow-up packet that contains more.
- */
+#define VMBUS_CHANPKT_SIZE_ALIGN (1 << VMBUS_CHANPKT_SIZE_SHIFT)
-struct hv_gpadl_header {
- struct hv_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t gpadl;
- uint16_t range_buf_len;
- uint16_t range_count;
- struct hv_gpa_range range[0];
-} __packed;
+#define VMBUS_CHANPKT_SETLEN(pktlen, len) \
+do { \
+ (pktlen) = (len) >> VMBUS_CHANPKT_SIZE_SHIFT; \
+} while (0)
-/* How many PFNs can be referenced by the header */
-#define HV_NPFNHDR \
- ((HV_MESSAGE_PAYLOAD - sizeof(struct hv_gpadl_header) - \
- sizeof(struct hv_gpa_range)) / sizeof(uint64_t))
-
-/*
- * This is the follow-up packet that contains more PFNs
- */
-struct hv_gpadl_body {
- struct hv_channel_msg_header header;
- uint32_t message_number;
- uint32_t gpadl;
- uint64_t pfn[0];
+struct vmbus_chanpkt {
+ struct vmbus_chanpkt_hdr cp_hdr;
} __packed;
-/* How many PFNs can be referenced by the body */
-#define HV_NPFNBODY \
- ((HV_MESSAGE_PAYLOAD - sizeof(struct hv_gpadl_body)) / \
- sizeof(uint64_t))
-
-struct hv_gpadl_created {
- struct hv_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t gpadl;
- uint32_t creation_status;
+struct vmbus_chanpkt_sglist {
+ struct vmbus_chanpkt_hdr cp_hdr;
+ uint32_t cp_rsvd;
+ uint32_t cp_gpa_cnt;
+ struct vmbus_gpa cp_gpa[0];
} __packed;
-struct hv_gpadl_teardown {
- struct hv_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t gpadl;
-} __packed;
-
-struct hv_gpadl_torndown {
- struct hv_channel_msg_header header;
- uint32_t gpadl;
+struct vmbus_chanpkt_prplist {
+ struct vmbus_chanpkt_hdr cp_hdr;
+ uint32_t cp_rsvd;
+ uint32_t cp_range_cnt;
+ struct vmbus_gpa_range cp_range[0];
} __packed;
/*
- * hv_vmbus_priv.h
+ * Channel messages
+ * - Embedded in vmbus_message.msg_data, e.g. response and notification.
+ * - Embedded in hypercall_postmsg_in.hc_data, e.g. request.
*/
-#define HV_MESSAGE_SIZE 256
-#define HV_MESSAGE_PAYLOAD 240
+#define VMBUS_CHANMSG_CHOFFER 1 /* NOTE */
+#define VMBUS_CHANMSG_CHRESCIND 2 /* NOTE */
+#define VMBUS_CHANMSG_CHREQUEST 3 /* REQ */
+#define VMBUS_CHANMSG_CHOFFER_DONE 4 /* NOTE */
+#define VMBUS_CHANMSG_CHOPEN 5 /* REQ */
+#define VMBUS_CHANMSG_CHOPEN_RESP 6 /* RESP */
+#define VMBUS_CHANMSG_CHCLOSE 7 /* REQ */
+#define VMBUS_CHANMSG_GPADL_CONN 8 /* REQ */
+#define VMBUS_CHANMSG_GPADL_SUBCONN 9 /* REQ */
+#define VMBUS_CHANMSG_GPADL_CONNRESP 10 /* RESP */
+#define VMBUS_CHANMSG_GPADL_DISCONN 11 /* REQ */
+#define VMBUS_CHANMSG_GPADL_DISCONNRESP 12 /* RESP */
+#define VMBUS_CHANMSG_CHFREE 13 /* REQ */
+#define VMBUS_CHANMSG_CONNECT 14 /* REQ */
+#define VMBUS_CHANMSG_CONNECT_RESP 15 /* RESP */
+#define VMBUS_CHANMSG_DISCONNECT 16 /* REQ */
+#define VMBUS_CHANMSG_COUNT 17
+#define VMBUS_CHANMSG_MAX 22
-/*
- * Hypervisor message IDs ???
- */
-#define HV_MESSAGE_CONNECTION_ID 1
-#define HV_MESSAGE_PORT_ID 1
-#define HV_EVENT_CONNECTION_ID 2
-#define HV_EVENT_PORT_ID 2
-#define HV_MONITOR_CONNECTION_ID 3
-#define HV_MONITOR_PORT_ID 3
-#define HV_MESSAGE_SINT 2
+struct vmbus_chanmsg_hdr {
+ uint32_t chm_type; /* VMBUS_CHANMSG_* */
+ uint32_t chm_rsvd;
+} __packed;
-/*
- * Hypervisor message types
- */
-#define HV_MESSAGE_TYPE_NONE 0x00000000
-#define HV_MESSAGE_TIMER_EXPIRED 0x80000010
+/* VMBUS_CHANMSG_CONNECT */
+struct vmbus_chanmsg_connect {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_ver;
+ uint32_t chm_rsvd;
+ uint64_t chm_evtflags;
+ uint64_t chm_mnf1;
+ uint64_t chm_mnf2;
+} __packed;
+
+/* VMBUS_CHANMSG_CONNECT_RESP */
+struct vmbus_chanmsg_connect_resp {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint8_t chm_done;
+} __packed;
+
+/* VMBUS_CHANMSG_CHREQUEST */
+struct vmbus_chanmsg_chrequest {
+ struct vmbus_chanmsg_hdr chm_hdr;
+} __packed;
+
+/* VMBUS_CHANMSG_DISCONNECT */
+struct vmbus_chanmsg_disconnect {
+ struct vmbus_chanmsg_hdr chm_hdr;
+} __packed;
+
+/* VMBUS_CHANMSG_CHOPEN */
+struct vmbus_chanmsg_chopen {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_openid;
+ uint32_t chm_gpadl;
+ uint32_t chm_vcpuid;
+ uint32_t chm_txbr_pgcnt;
+#define VMBUS_CHANMSG_CHOPEN_UDATA_SIZE 120
+ uint8_t chm_udata[VMBUS_CHANMSG_CHOPEN_UDATA_SIZE];
+} __packed;
+
+/* VMBUS_CHANMSG_CHOPEN_RESP */
+struct vmbus_chanmsg_chopen_resp {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_openid;
+ uint32_t chm_status;
+} __packed;
+
+/* VMBUS_CHANMSG_GPADL_CONN */
+struct vmbus_chanmsg_gpadl_conn {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_gpadl;
+ uint16_t chm_range_len;
+ uint16_t chm_range_cnt;
+ struct vmbus_gpa_range chm_range;
+} __packed;
+
+#define VMBUS_CHANMSG_GPADL_CONN_PGMAX 26
+
+/* VMBUS_CHANMSG_GPADL_SUBCONN */
+struct vmbus_chanmsg_gpadl_subconn {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_msgno;
+ uint32_t chm_gpadl;
+ uint64_t chm_gpa_page[0];
+} __packed;
+
+#define VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX 28
+
+/* VMBUS_CHANMSG_GPADL_CONNRESP */
+struct vmbus_chanmsg_gpadl_connresp {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_gpadl;
+ uint32_t chm_status;
+} __packed;
+
+/* VMBUS_CHANMSG_CHCLOSE */
+struct vmbus_chanmsg_chclose {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+} __packed;
+
+/* VMBUS_CHANMSG_GPADL_DISCONN */
+struct vmbus_chanmsg_gpadl_disconn {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_gpadl;
+} __packed;
+
+/* VMBUS_CHANMSG_CHFREE */
+struct vmbus_chanmsg_chfree {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+} __packed;
-struct hv_monitor_trigger_state {
- uint32_t group_enable :4;
- uint32_t reserved :28;
-};
+/* VMBUS_CHANMSG_CHRESCIND */
+struct vmbus_chanmsg_chrescind {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+} __packed;
-struct hv_monitor_trigger_group {
- uint32_t pending;
- uint32_t armed;
-};
+/* VMBUS_CHANMSG_CHOFFER */
+struct vmbus_chanmsg_choffer {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ struct hv_guid chm_chtype;
+ struct hv_guid chm_chinst;
+ uint64_t chm_chlat; /* unit: 100ns */
+ uint32_t chm_chrev;
+ uint32_t chm_svrctx_sz;
+ uint16_t chm_chflags;
+ uint16_t chm_mmio_sz; /* unit: MB */
+ uint8_t chm_udata[120];
+ uint16_t chm_subidx;
+ uint16_t chm_rsvd;
+ uint32_t chm_chanid;
+ uint8_t chm_montrig;
+ uint8_t chm_flags1; /* VMBUS_CHOFFER_FLAG1_ */
+ uint16_t chm_flags2;
+ uint32_t chm_connid;
+} __packed;
-struct hv_monitor_parameter {
- uint32_t connection_id;
- uint16_t flag_number;
- uint16_t reserved;
-};
+#define VMBUS_CHOFFER_FLAG1_HASMNF 0x01
/*
- * Monitor page Layout
- * ------------------------------------------------------
- * | 0 | trigger_state (4 bytes) | reserved1 (4 bytes) |
- * | 8 | trigger_group[0] |
- * | 10 | trigger_group[1] |
- * | 18 | trigger_group[2] |
- * | 20 | trigger_group[3] |
- * | 28 | reserved2[0] |
- * | 30 | reserved2[1] |
- * | 38 | reserved2[2] |
- * | 40 | next_check_time[0][0] | next_check_time[0][1] |
- * | ... |
- * | 240 | latency[0][0..3] |
- * | 340 | reserved3[0] |
- * | 440 | parameter[0][0] |
- * | 448 | parameter[0][1] |
- * | ... |
- * | 840 | reserved4[0] |
- * ------------------------------------------------------
+ * =============================================================================
+ * Temporary
+ * =============================================================================
*/
-struct hv_monitor_page {
- struct hv_monitor_trigger_state trigger_state;
- uint32_t reserved1;
-
- struct hv_monitor_trigger_group trigger_group[4];
- uint64_t reserved2[3];
- int32_t next_check_time[4][32];
+ /*
+ * Common defines for Hyper-V ICs
+ */
+#define HV_ICMSGTYPE_NEGOTIATE 0
+#define HV_ICMSGTYPE_HEARTBEAT 1
+#define HV_ICMSGTYPE_KVPEXCHANGE 2
+#define HV_ICMSGTYPE_SHUTDOWN 3
+#define HV_ICMSGTYPE_TIMESYNC 4
+#define HV_ICMSGTYPE_VSS 5
- uint16_t latency[4][32];
- uint64_t reserved3[32];
+#define HV_ICMSGHDRFLAG_TRANSACTION 1
+#define HV_ICMSGHDRFLAG_REQUEST 2
+#define HV_ICMSGHDRFLAG_RESPONSE 4
- struct hv_monitor_parameter parameter[4][32];
-
- uint8_t reserved4[1984];
-};
-
-struct hv_input_post_message {
- uint32_t connection_id;
- uint32_t reserved;
- uint32_t message_type;
- uint32_t payload_size;
- uint8_t payload[HV_MESSAGE_PAYLOAD];
+struct hv_pipe_hdr {
+ uint32_t flags;
+ uint32_t msgsize;
} __packed;
-/*
- * Synthetic interrupt controller event flags
- */
-struct hv_synic_event_flags {
- uint32_t flags[64];
+struct hv_ic_version {
+ uint16_t major;
+ uint16_t minor;
} __packed;
-#define HV_X64_MSR_GUEST_OS_ID 0x40000000
-#define HV_X64_MSR_HYPERCALL 0x40000001
-#define HV_X64_MSR_HYPERCALL_ENABLED (1 << 0)
-#define HV_X64_MSR_HYPERCALL_PASHIFT 12
-#define HV_X64_MSR_VP_INDEX 0x40000002
-#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
+struct hv_icmsg_hdr {
+ struct hv_ic_version icverframe;
+ uint16_t icmsgtype;
+ struct hv_ic_version icvermsg;
+ uint16_t icmsgsize;
+ uint32_t status;
+ uint8_t ictransaction_id;
+ uint8_t icflags;
+ uint8_t reserved[2];
+} __packed;
-#define HV_S_OK 0x00000000
-#define HV_E_FAIL 0x80004005
-#define HV_ERROR_NOT_SUPPORTED 0x80070032
-#define HV_ERROR_MACHINE_LOCKED 0x800704f7
+#define HV_ICMSG_STATUS_OK 0x00000000
+#define HV_ICMSG_STATUS_FAIL 0x80004005
-/*
- * Synthetic interrupt controller message header
- */
-struct hv_vmbus_msg_header {
- uint32_t message_type;
- uint8_t payload_size;
- uint8_t message_flags;
-#define HV_SYNIC_MHF_PENDING 0x0001
- uint8_t reserved[2];
- union {
- uint64_t sender;
- uint32_t port;
- } u;
+struct hv_icmsg_negotiate {
+ uint16_t icframe_vercnt;
+ uint16_t icmsg_vercnt;
+ uint32_t reserved;
+ struct hv_ic_version icversion_data[1]; /* any size array */
} __packed;
-/*
- * Define synthetic interrupt controller message format
- */
-struct hv_vmbus_message {
- struct hv_vmbus_msg_header header;
- uint64_t payload[30];
+struct hv_shutdown_msg {
+ uint32_t reason_code;
+ uint32_t timeout_seconds;
+ uint32_t flags;
+ uint8_t display_message[2048];
} __packed;
-/*
- * Maximum channels is determined by the size of the interrupt
- * page which is PAGE_SIZE. 1/2 of PAGE_SIZE is for
- * send endpoint interrupt and the other is receive
- * endpoint interrupt.
- *
- * Note: (PAGE_SIZE >> 1) << 3 allocates 16348 channels
- */
-#define HV_MAX_NUM_CHANNELS ((PAGE_SIZE >> 1) << 3)
-#define HV_MAX_NUM_CHANNELS_SUPPORTED 256
-
-/* Virtual APIC registers */
-#define HV_X64_MSR_EOI 0x40000070
-#define HV_X64_MSR_ICR 0x40000071
-#define HV_X64_MSR_TPR 0x40000072
-#define HV_X64_MSR_APIC_ASSIST_PAGE 0x40000073
-#define HV_APIC_ASSIST_PAGE_PASHIFT 12
+struct hv_timesync_msg {
+ uint64_t parent_time;
+ uint64_t child_time;
+ uint64_t round_trip_time;
+ uint8_t flags;
+#define HV_TIMESYNC_PROBE 0
+#define HV_TIMESYNC_SYNC 1
+#define HV_TIMESYNC_SAMPLE 2
+} __packed;
-/*
- * Synthetic interrupt controller model specific registers
- */
-/* Synthetic Interrupt Controll registers */
-#define HV_X64_MSR_SCONTROL 0x40000080
-#define HV_X64_MSR_SCONTROL_ENABLED (1<<0)
-#define HV_X64_MSR_SVERSION 0x40000081
-/* Synthetic Interrupt Event Flags Page register */
-#define HV_X64_MSR_SIEFP 0x40000082
-#define HV_X64_MSR_SIEFP_ENABLED (1<<0)
-#define HV_X64_MSR_SIEFP_PASHIFT 12
-/* Synthetic Interrupt Message Page register */
-#define HV_X64_MSR_SIMP 0x40000083
-#define HV_X64_MSR_SIMP_ENABLED (1<<0)
-#define HV_X64_MSR_SIMP_PASHIFT 12
-#define HV_X64_MSR_EOM 0x40000084
-
-#define HV_X64_MSR_SINT0 0x40000090
-#define HV_X64_MSR_SINT1 0x40000091
-#define HV_X64_MSR_SINT2 0x40000092
-#define HV_X64_MSR_SINT3 0x40000093
-#define HV_X64_MSR_SINT4 0x40000094
-#define HV_X64_MSR_SINT5 0x40000095
-#define HV_X64_MSR_SINT6 0x40000096
-#define HV_X64_MSR_SINT7 0x40000097
-#define HV_X64_MSR_SINT8 0x40000098
-#define HV_X64_MSR_SINT9 0x40000099
-#define HV_X64_MSR_SINT10 0x4000009A
-#define HV_X64_MSR_SINT11 0x4000009B
-#define HV_X64_MSR_SINT12 0x4000009C
-#define HV_X64_MSR_SINT13 0x4000009D
-#define HV_X64_MSR_SINT14 0x4000009E
-#define HV_X64_MSR_SINT15 0x4000009F
-#define HV_X64_MSR_SINT_VECTOR 0xff
-#define HV_X64_MSR_SINT_MASKED (1<<16)
-#define HV_X64_MSR_SINT_AUTOEOI (1<<17)
+struct hv_heartbeat_msg {
+ uint64_t seq_num;
+ uint32_t reserved[8];
+} __packed;
/*
- * Hypercalls
+ * =============================================================================
+ * Helper macros
+ * =============================================================================
*/
-#define HV_CALL_POST_MESSAGE 0x005c
-#define HV_CALL_SIGNAL_EVENT 0x005d
-/*
- * Hypercall status codes
- */
-#define HV_STATUS_SUCCESS 0
-#define HV_STATUS_INVALID_HYPERCALL_CODE 2
-#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
-#define HV_STATUS_INVALID_ALIGNMENT 4
-#define HV_STATUS_INSUFFICIENT_MEMORY 11
-#define HV_STATUS_INVALID_CONNECTION_ID 18
-#define HV_STATUS_INSUFFICIENT_BUFFERS 19
+/* How many PFNs can be referenced by the header */
+#define HV_NPFNHDR ((VMBUS_MSG_DSIZE_MAX - \
+ sizeof(struct vmbus_chanmsg_gpadl_conn)) / sizeof(uint64_t))
-/*
- * XXX: Hypercall signal input structure
- */
-struct hv_input_signal_event {
- uint32_t connection_id;
- uint16_t flag_number;
- uint16_t reserved;
-} __packed;
+/* How many PFNs can be referenced by the body */
+#define HV_NPFNBODY ((VMBUS_MSG_DSIZE_MAX - \
+ sizeof(struct vmbus_chanmsg_gpadl_subconn)) / sizeof(uint64_t))
#endif /* _HYPERVREG_H_ */