1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-22 11:17:19 +00:00

hyperv/vmbus: Reduce the # of event loops by recording event flag count

Use vmbus softc to save vmbus per-cpu data.  More stuffs will be moved
into vmbus softc.

MFC after:	1 week
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D6403
This commit is contained in:
Sepherosa Ziehau 2016-05-18 03:19:53 +00:00
parent 8080722aee
commit 008024f2b8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=300102
4 changed files with 112 additions and 17 deletions

View File

@ -42,7 +42,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include "hv_vmbus_priv.h"
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
static int vmbus_channel_create_gpadl_header(
/* must be phys and virt contiguous*/
@ -199,6 +200,8 @@ hv_vmbus_channel_open(
new_channel->on_channel_callback = pfn_on_channel_callback;
new_channel->channel_callback_context = context;
vmbus_on_channel_open(new_channel);
new_channel->rxq = hv_vmbus_g_context.hv_event_queue[new_channel->target_cpu];
TASK_INIT(&new_channel->channel_task, 0, VmbusProcessChannelEvent, new_channel);

View File

@ -38,7 +38,8 @@
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include "hv_vmbus_priv.h"
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
/*
* Globals
@ -294,10 +295,10 @@ hv_vmbus_disconnect(void) {
void
hv_vmbus_on_events(int cpu)
{
unsigned long *intr_page;
unsigned long *intr_flags;
hv_vmbus_synic_event_flags *event;
void *page_addr;
int page_cnt, pg;
int flag_cnt, f;
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
"cpu out of range!"));
@ -307,13 +308,13 @@ hv_vmbus_on_events(int cpu)
page_addr + HV_VMBUS_MESSAGE_SINT;
if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
page_cnt = HV_MAX_NUM_CHANNELS_SUPPORTED >>
flag_cnt = HV_MAX_NUM_CHANNELS_SUPPORTED >>
HV_CHANNEL_ULONG_SHIFT;
/*
* receive size is 1/2 page and divide that by 4 bytes
*/
if (atomic_testandclear_int(&event->flags32[0], 0))
intr_page = hv_vmbus_g_connection.recv_interrupt_page;
intr_flags = hv_vmbus_g_connection.recv_interrupt_page;
else
return;
} else {
@ -322,23 +323,23 @@ hv_vmbus_on_events(int cpu)
* checked directly to get the id of the channel
* that has the pending interrupt.
*/
page_cnt = HV_EVENT_FLAGS_ULONG_COUNT;
intr_page = event->flagsul;
flag_cnt = VMBUS_PCPU_GET(event_flag_cnt, cpu);
intr_flags = event->flagsul;
}
/*
* Check events
*/
for (pg = 0; pg < page_cnt; pg++) {
for (f = 0; f < flag_cnt; f++) {
uint32_t rel_id_base;
int bit;
if (intr_page[pg] == 0)
if (intr_flags[f] == 0)
continue;
rel_id_base = pg << HV_CHANNEL_ULONG_SHIFT;
rel_id_base = f << HV_CHANNEL_ULONG_SHIFT;
for (bit = 0; bit < HV_CHANNEL_ULONG_LEN; bit++) {
if (atomic_testandclear_long(&intr_page[pg], bit)) {
if (atomic_testandclear_long(&intr_flags[f], bit)) {
struct hv_vmbus_channel *channel;
uint32_t rel_id;
@ -412,3 +413,30 @@ hv_vmbus_set_event(hv_vmbus_channel *channel) {
return (ret);
}
void
vmbus_on_channel_open(const struct hv_vmbus_channel *chan)
{
volatile int *flag_cnt_ptr;
int flag_cnt;
flag_cnt = (chan->offer_msg.child_rel_id / HV_CHANNEL_ULONG_LEN) + 1;
flag_cnt_ptr = VMBUS_PCPU_PTR(event_flag_cnt, chan->target_cpu);
for (;;) {
int old_flag_cnt;
old_flag_cnt = *flag_cnt_ptr;
if (old_flag_cnt >= flag_cnt)
break;
if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) {
if (bootverbose) {
printf("VMBUS: channel%u update "
"cpu%d flag_cnt to %d\n",
chan->offer_msg.child_rel_id,
chan->target_cpu, flag_cnt);
}
break;
}
}
}

View File

@ -60,11 +60,14 @@ __FBSDID("$FreeBSD$");
#include <x86/apicvar.h>
#include <dev/hyperv/include/hyperv.h>
#include "hv_vmbus_priv.h"
#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
#include <contrib/dev/acpica/include/acpi.h>
#include "acpi_if.h"
struct vmbus_softc *vmbus_sc;
static device_t vmbus_devp;
static int vmbus_inited;
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
@ -517,7 +520,9 @@ vmbus_attach(device_t dev)
{
if(bootverbose)
device_printf(dev, "VMBUS: attach dev: %p\n", dev);
vmbus_devp = dev;
vmbus_sc = device_get_softc(dev);
#ifndef EARLY_AP_STARTUP
/*
@ -537,7 +542,7 @@ vmbus_attach(device_t dev)
static void
vmbus_init(void)
{
if (vm_guest != VM_GUEST_HV)
if (vm_guest != VM_GUEST_HV || vmbus_get_softc() == NULL)
return;
#ifndef EARLY_AP_STARTUP
@ -646,9 +651,11 @@ static device_method_t vmbus_methods[] = {
{ 0, 0 } };
static char driver_name[] = "vmbus";
static driver_t vmbus_driver = { driver_name, vmbus_methods,0, };
static driver_t vmbus_driver = {
"vmbus",
vmbus_methods,
sizeof(struct vmbus_softc)
};
devclass_t vmbus_devclass;

View File

@ -0,0 +1,57 @@
/*-
* 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_VAR_H_
#define _VMBUS_VAR_H_
#include <sys/param.h>
struct vmbus_pcpu_data {
int event_flag_cnt; /* # of event flags */
} __aligned(CACHE_LINE_SIZE);
struct vmbus_softc {
struct vmbus_pcpu_data vmbus_pcpu[MAXCPU];
};
extern struct vmbus_softc *vmbus_sc;
static __inline struct vmbus_softc *
vmbus_get_softc(void)
{
return vmbus_sc;
}
#define VMBUS_PCPU_GET(field, cpu) \
(vmbus_get_softc())->vmbus_pcpu[cpu].field
#define VMBUS_PCPU_PTR(field, cpu) \
&(vmbus_get_softc())->vmbus_pcpu[cpu].field
void vmbus_on_channel_open(const struct hv_vmbus_channel *);
#endif /* !_VMBUS_VAR_H_ */