Index: sys/conf/files.amd64 =================================================================== --- sys/conf/files.amd64 +++ sys/conf/files.amd64 @@ -275,6 +275,7 @@ dev/hyperv/vmbus/hv_et.c optional hyperv dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv +dev/hyperv/stats/hv_stats.c optional hyperv dev/nfe/if_nfe.c optional nfe pci dev/ntb/if_ntb/if_ntb.c optional if_ntb dev/ntb/ntb_hw/ntb_hw.c optional if_ntb | ntb_hw Index: sys/conf/files.i386 =================================================================== --- sys/conf/files.i386 +++ sys/conf/files.i386 @@ -249,6 +249,7 @@ dev/hyperv/vmbus/hv_et.c optional hyperv dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv +dev/hyperv/stats/hv_stats.c optional hyperv dev/ichwd/ichwd.c optional ichwd dev/if_ndis/if_ndis.c optional ndis dev/if_ndis/if_ndis_pccard.c optional ndis pccard Index: sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c =================================================================== --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -113,6 +113,7 @@ #include #include +#include #include "hv_net_vsc.h" #include "hv_rndis.h" #include "hv_rndis_filter.h" @@ -480,6 +481,10 @@ hn_tx_chimney_size < sc->hn_tx_chimney_max) hn_set_tx_chimney_size(sc, hn_tx_chimney_size); + ring_buffer_stat(device_get_sysctl_ctx(dev), + device_get_name(dev), device_get_unit(dev), + device_ctx->channel); + return (0); failed: hn_destroy_tx_data(sc); Index: sys/dev/hyperv/stats/hv_stats.h =================================================================== --- /dev/null +++ sys/dev/hyperv/stats/hv_stats.h @@ -0,0 +1,42 @@ +/*- + * 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$ + */ + +/* + * Statistic for all hyper-V services. + */ +#ifndef __HYPERV_STATS_H__ +#define __HYPERV_STATS_H__ +#include + +void +ring_buffer_stat( + struct sysctl_ctx_list *ctx, + const char *devname, + int uint, + hv_vmbus_channel *channel); +#endif Index: sys/dev/hyperv/stats/hv_stats.c =================================================================== --- /dev/null +++ sys/dev/hyperv/stats/hv_stats.c @@ -0,0 +1,111 @@ +/*- + * 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$ + */ +#include +#include +#include "hv_stats.h" + +SYSCTL_DECL(_hw_hyperv); + +static char rbi_stats[256]; + +static int +rbi_sysctl_stats(SYSCTL_HANDLER_ARGS) +{ + hv_vmbus_ring_buffer_info* rbi; + uint32_t read_index, write_index, interrupt_mask, sz; + uint32_t read_avail, write_avail; + + rbi = (hv_vmbus_ring_buffer_info*)arg1; + read_index = rbi->ring_buffer->read_index; + write_index = rbi->ring_buffer->write_index; + interrupt_mask = rbi->ring_buffer->interrupt_mask; + sz = rbi->ring_data_size; + write_avail = hv_bytes_avail_to_write(read_index, + write_index, sz); + read_avail = sz - write_avail; + snprintf(rbi_stats, sizeof(rbi_stats), + "r_idx: %d " + "w_idx: %d " + "int_mask: %d " + "r_avail: %d " + "w_avail: %d", + read_index, write_index, interrupt_mask, + read_avail, write_avail); + + return (sysctl_handle_string(oidp, rbi_stats, + sizeof(rbi_stats), req)); +} + +#define RBI_SYSCTL_STAT(rbi, ctx, desc, parent, oid) \ + SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, oid, \ + CTLTYPE_STRING|CTLFLAG_RD, rbi, 0, \ + rbi_sysctl_stats, "A", desc) +void +ring_buffer_stat(struct sysctl_ctx_list *ctx, + const char* devname, + int unit, hv_vmbus_channel* channel) +{ + struct sysctl_oid *dev_sysctl, *devunit_sysctl, *devch_sysctl; + struct sysctl_oid *devch_id_sysctl; + struct sysctl_oid *devch_id_out_sysctl, *devch_id_in_sysctl; + + char name[16]; + /* This creates hw.hyperv.DEVNAME tree */ + dev_sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw_hyperv), + OID_AUTO, devname, CTLFLAG_RD, 0, ""); + /* This creates hw.hyperv.DEVNAME.DEVUNIT tree */ + snprintf(name, sizeof(name), "%d", unit); + devunit_sysctl = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(dev_sysctl), + OID_AUTO, name, CTLFLAG_RD, 0, ""); + /* This creates hw.hyperv.DEVNAME.DEVUNIT.channel tree */ + devch_sysctl = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(devunit_sysctl), + OID_AUTO, "channel", CTLFLAG_RD, 0, ""); + /* This creates hw.hyperv.DEVNAME.DEVUNIT.channel.CHANID tree */ + snprintf(name, sizeof(name), "%d", channel->offer_msg.child_rel_id); + devch_id_sysctl = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(devch_sysctl), + OID_AUTO, name, CTLFLAG_RD, 0, ""); + + devch_id_out_sysctl = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(devch_id_sysctl), + OID_AUTO, "out", CTLFLAG_RD, 0, ""); + devch_id_in_sysctl = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(devch_id_sysctl), + OID_AUTO, "in", CTLFLAG_RD, 0, ""); + + RBI_SYSCTL_STAT(&(channel->outbound), ctx, + "outbound ring buffer stats", + SYSCTL_CHILDREN(devch_id_out_sysctl), + "ring_buffer_stats"); + RBI_SYSCTL_STAT(&(channel->inbound), ctx, + "inbound ring buffer stats", + SYSCTL_CHILDREN(devch_id_in_sysctl), + "ring_buffer_stats"); +} Index: sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c =================================================================== --- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -72,6 +72,7 @@ #include #include +#include #include "hv_vstorage.h" #define STORVSC_RINGBUFFER_SIZE (20*PAGE_SIZE) @@ -1106,6 +1107,9 @@ mtx_unlock(&sc->hs_lock); + ring_buffer_stat(device_get_sysctl_ctx(dev), + device_get_name(dev), device_get_unit(dev), + hv_dev->channel); root_mount_rel(root_mount_token); return (0); Index: sys/dev/hyperv/vmbus/hv_ring_buffer.c =================================================================== --- sys/dev/hyperv/vmbus/hv_ring_buffer.c +++ sys/dev/hyperv/vmbus/hv_ring_buffer.c @@ -33,15 +33,11 @@ #include "hv_vmbus_priv.h" -/* Amount of space to write to */ -#define HV_BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r))? \ - ((z) - ((w) - (r))):((r) - (w)) - /** * @brief Get number of bytes available to read and to write to * for the specified ring buffer */ -static inline void +void get_ring_buffer_avail_bytes( hv_vmbus_ring_buffer_info* rbi, uint32_t* read, @@ -55,7 +51,7 @@ read_loc = rbi->ring_buffer->read_index; write_loc = rbi->ring_buffer->write_index; - *write = HV_BYTES_AVAIL_TO_WRITE( + *write = hv_bytes_avail_to_write( read_loc, write_loc, rbi->ring_data_size); *read = rbi->ring_data_size - *write; } Index: sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c =================================================================== --- sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -69,7 +69,10 @@ static hv_setup_args setup_args; /* only CPU 0 supported at this time */ static char *vmbus_ids[] = { "VMBUS", NULL }; - +/** + * sysctl root tree node for statistic information : hw.hyperv + */ +SYSCTL_NODE(_hw, OID_AUTO, hyperv, CTLFLAG_RD, NULL, "Hyper-V"); /** * @brief Software interrupt thread routine to handle channel messages from * the hypervisor. Index: sys/dev/hyperv/vmbus/hv_vmbus_priv.h =================================================================== --- sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -640,6 +640,23 @@ * Private, VM Bus functions */ +/* Amount of space to write to */ +inline +uint32_t hv_bytes_avail_to_write( + uint32_t read, + uint32_t write, + uint32_t sz) { + uint32_t result = (write >= read) ? + (sz - (write - read)) : + (read - write); + return (result); + } + +void get_ring_buffer_avail_bytes( + hv_vmbus_ring_buffer_info* rbi, + uint32_t* read, + uint32_t* write); + int hv_vmbus_ring_buffer_init( hv_vmbus_ring_buffer_info *ring_info, void *buffer, Index: sys/modules/hyperv/stats/Makefile =================================================================== --- /dev/null +++ sys/modules/hyperv/stats/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/hyperv/stats + +KMOD= hv_stats +SRCS= hv_stats.c + +CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \ + -I${.CURDIR}/../../../dev/hyperv/vmbus + +.include