hyperv/vmbus: Redefine SynIC message.

- Avoid unnecessary indirection.
- Avoid bit fields.
- Use __packed.

Reviewed by:	Jun Su <junsu microsoft com>
MFC after:	1 week
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D6636
This commit is contained in:
Sepherosa Ziehau 2016-05-31 05:18:55 +00:00
parent 3b2f526463
commit 3ae6d31281
3 changed files with 80 additions and 56 deletions

View File

@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
#include <dev/hyperv/vmbus/hyperv_reg.h>
#include <dev/hyperv/vmbus/hyperv_var.h>
#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
#include <contrib/dev/acpica/include/acpi.h>
@ -76,7 +77,7 @@ static void
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 @@ vmbus_msg_task(void *xsc, int pending __unused)
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 @@ vmbus_msg_task(void *xsc, int pending __unused)
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 @@ handled:
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 @@ vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
* 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 @@ vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
* 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));
}

View File

@ -251,43 +251,8 @@ typedef union _hv_vmbus_port_id {
} 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

View File

@ -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 <sys/param.h>
/*
* 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_ */