Index: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include @@ -76,7 +77,7 @@ vmbus_msg_task(void *xsc, int pending __unused) { struct vmbus_softc *sc = xsc; - hv_vmbus_message *msg; + volatile struct vmbus_message *msg; msg = VMBUS_PCPU_GET(sc, message, curcpu) + VMBUS_SINT_MESSAGE; for (;;) { @@ -84,10 +85,12 @@ hv_vmbus_channel_msg_header *hdr; hv_vmbus_channel_msg_type msg_type; - if (msg->header.message_type == HV_MESSAGE_TYPE_NONE) + if (msg->msg_type == VMBUS_MSGTYPE_NONE) break; /* no message */ - hdr = (hv_vmbus_channel_msg_header *)msg->u.payload; + /* XXX: update messageHandler interface */ + hdr = __DEVOLATILE(hv_vmbus_channel_msg_header *, + msg->msg_data); msg_type = hdr->message_type; if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) { @@ -99,20 +102,20 @@ if (entry->messageHandler) entry->messageHandler(hdr); handled: - msg->header.message_type = HV_MESSAGE_TYPE_NONE; + msg->msg_type = VMBUS_MSGTYPE_NONE; /* - * Make sure the write to message_type (ie set to - * HV_MESSAGE_TYPE_NONE) happens before we read the - * message_pending and EOMing. Otherwise, the EOMing will - * not deliver any more messages - * since there is no empty slot + * Make sure the write to msg_type (i.e. set to + * VMBUS_MSGTYPE_NONE) happens before we read the + * msg_flags and EOMing. Otherwise, the EOMing will + * not deliver any more messages since there is no + * empty slot * * NOTE: * mb() is used here, since atomic_thread_fence_seq_cst() * will become compiler fence on UP kernel. */ mb(); - if (msg->header.message_flags.u.message_pending) { + if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) { /* * This will cause message queue rescan to possibly * deliver another msg from the hypervisor @@ -125,7 +128,8 @@ static __inline int vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu) { - hv_vmbus_message *msg, *msg_base; + volatile struct vmbus_message *msg; + struct vmbus_message *msg_base; msg_base = VMBUS_PCPU_GET(sc, message, cpu); @@ -135,25 +139,24 @@ * TODO: move this to independent IDT vector. */ msg = msg_base + VMBUS_SINT_TIMER; - if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) { - msg->header.message_type = HV_MESSAGE_TYPE_NONE; + if (msg->msg_type == VMBUS_MSGTYPE_TIMER_EXPIRED) { + msg->msg_type = VMBUS_MSGTYPE_NONE; vmbus_et_intr(frame); /* - * Make sure the write to message_type (ie set to - * HV_MESSAGE_TYPE_NONE) happens before we read the - * message_pending and EOMing. Otherwise, the EOMing will - * not deliver any more messages - * since there is no empty slot + * Make sure the write to msg_type (i.e. set to + * VMBUS_MSGTYPE_NONE) happens before we read the + * msg_flags and EOMing. Otherwise, the EOMing will + * not deliver any more messages since there is no + * empty slot * * NOTE: * mb() is used here, since atomic_thread_fence_seq_cst() * will become compiler fence on UP kernel. */ mb(); - - if (msg->header.message_flags.u.message_pending) { + if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) { /* * This will cause message queue rescan to possibly * deliver another msg from the hypervisor @@ -175,7 +178,7 @@ * Check messages. Mainly management stuffs; ultra low rate. */ msg = msg_base + VMBUS_SINT_MESSAGE; - if (__predict_false(msg->header.message_type != HV_MESSAGE_TYPE_NONE)) { + if (__predict_false(msg->msg_type != VMBUS_MSGTYPE_NONE)) { taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu), VMBUS_PCPU_PTR(sc, message_task, cpu)); } Index: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h =================================================================== --- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -251,44 +251,9 @@ } u ; } hv_vmbus_port_id; -/* - * Define synthetic interrupt controller message flag - */ -typedef union { - uint8_t as_uint8_t; - struct { - uint8_t message_pending:1; - uint8_t reserved:7; - } u; -} hv_vmbus_msg_flags; - typedef uint64_t hv_vmbus_partition_id; /* - * Define synthetic interrupt controller message header - */ -typedef struct { - hv_vmbus_msg_type message_type; - uint8_t payload_size; - hv_vmbus_msg_flags message_flags; - uint8_t reserved[2]; - union { - hv_vmbus_partition_id sender; - hv_vmbus_port_id port; - } u; -} hv_vmbus_msg_header; - -/* - * Define synthetic interrupt controller message format - */ -typedef struct vmbus_message { - hv_vmbus_msg_header header; - union { - uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; - } u ; -} hv_vmbus_message; - -/* * 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 Index: head/sys/dev/hyperv/vmbus/vmbus_reg.h =================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_reg.h +++ head/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -0,0 +1,56 @@ +/*- + * 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$ + */ + +#ifndef _VMBUS_REG_H_ +#define _VMBUS_REG_H_ + +#include + +/* + * Hyper-V SynIC message format. + */ + +#define VMBUS_MSG_DSIZE_MAX 240 +#define VMBUS_MSG_SIZE 256 + +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; +CTASSERT(sizeof(struct vmbus_message) == VMBUS_MSG_SIZE); + +#define VMBUS_MSGTYPE_NONE 0 +#define VMBUS_MSGTYPE_TIMER_EXPIRED 0x80000010 + +#define VMBUS_MSGFLAG_PENDING 0x01 + +#endif /* !_VMBUS_REG_H_ */