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:
parent
3b2f526463
commit
3ae6d31281
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
56
sys/dev/hyperv/vmbus/vmbus_reg.h
Normal file
56
sys/dev/hyperv/vmbus/vmbus_reg.h
Normal 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_ */
|
Loading…
x
Reference in New Issue
Block a user