Author: sephe
Date: Thu Jan 14 03:05:10 2016
New Revision: 293873
URL: https://svnweb.freebsd.org/changeset/base/293873

Log:
  hyperv: implement an event timer
  
  Submitted by:         Howard Su <howard...@gmail.com>
  Reviewed by:          delphij, royger, adrian
  Approved by:          adrian (mentor)
  Sponsored by:         Microsoft OSTC
  Differential Revision:        https://reviews.freebsd.org/D4676

Added:
  head/sys/dev/hyperv/vmbus/hv_et.c   (contents, props changed)
Modified:
  head/sys/conf/files.amd64
  head/sys/conf/files.i386
  head/sys/dev/hyperv/vmbus/hv_hv.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  head/sys/modules/hyperv/vmbus/Makefile

Modified: head/sys/conf/files.amd64
==============================================================================
--- head/sys/conf/files.amd64   Thu Jan 14 02:58:28 2016        (r293872)
+++ head/sys/conf/files.amd64   Thu Jan 14 03:05:10 2016        (r293873)
@@ -273,6 +273,7 @@ dev/hyperv/vmbus/hv_channel.c                               
optiona
 dev/hyperv/vmbus/hv_channel_mgmt.c                     optional        hyperv
 dev/hyperv/vmbus/hv_connection.c                       optional        hyperv
 dev/hyperv/vmbus/hv_hv.c                               optional        hyperv
+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/nfe/if_nfe.c               optional        nfe pci

Modified: head/sys/conf/files.i386
==============================================================================
--- head/sys/conf/files.i386    Thu Jan 14 02:58:28 2016        (r293872)
+++ head/sys/conf/files.i386    Thu Jan 14 03:05:10 2016        (r293873)
@@ -247,6 +247,7 @@ dev/hyperv/vmbus/hv_channel.c                               
optiona
 dev/hyperv/vmbus/hv_channel_mgmt.c                     optional        hyperv
 dev/hyperv/vmbus/hv_connection.c                       optional        hyperv
 dev/hyperv/vmbus/hv_hv.c                               optional        hyperv
+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/ichwd/ichwd.c              optional ichwd

Added: head/sys/dev/hyperv/vmbus/hv_et.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hyperv/vmbus/hv_et.c   Thu Jan 14 03:05:10 2016        
(r293873)
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2015 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+#include <sys/time.h>
+#include <sys/timeet.h>
+
+#include "hv_vmbus_priv.h"
+
+#define HV_TIMER_FREQUENCY             (10 * 1000 * 1000LL) /* 100ns period */
+#define HV_MAX_DELTA_TICKS             0xffffffffLL
+#define HV_MIN_DELTA_TICKS             1LL
+
+static struct eventtimer et;
+static uint64_t periodticks[MAXCPU];
+
+static inline uint64_t
+sbintime2tick(sbintime_t time)
+{
+       struct timespec val;
+
+       val = sbttots(time);
+       return val.tv_sec * HV_TIMER_FREQUENCY + val.tv_nsec / 100;
+}
+
+static int
+hv_et_start(struct eventtimer *et, sbintime_t firsttime, sbintime_t periodtime)
+{
+       union hv_timer_config timer_cfg;
+       uint64_t current;
+
+       timer_cfg.as_uint64 = 0;
+       timer_cfg.auto_enable = 1;
+       timer_cfg.sintx = HV_VMBUS_MESSAGE_SINT;
+
+       periodticks[curcpu] = sbintime2tick(periodtime);
+       if (firsttime == 0)
+               firsttime = periodtime;
+
+       current = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
+       current += sbintime2tick(firsttime);
+
+       wrmsr(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
+       wrmsr(HV_X64_MSR_STIMER0_COUNT, current);
+
+       return (0);
+}
+
+static int
+hv_et_stop(struct eventtimer *et)
+{
+       wrmsr(HV_X64_MSR_STIMER0_CONFIG, 0);
+       wrmsr(HV_X64_MSR_STIMER0_COUNT, 0);
+
+       return (0);
+}
+
+void
+hv_et_intr(struct trapframe *frame)
+{
+       union hv_timer_config timer_cfg;
+       struct trapframe *oldframe;
+       struct thread *td;
+
+       if (periodticks[curcpu] != 0) {
+               uint64_t tick = sbintime2tick(periodticks[curcpu]);
+               timer_cfg.as_uint64 = rdmsr(HV_X64_MSR_STIMER0_CONFIG);
+               timer_cfg.enable = 0;
+               timer_cfg.auto_enable = 1;
+               timer_cfg.periodic = 1;
+               periodticks[curcpu] = 0;
+
+               wrmsr(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
+               wrmsr(HV_X64_MSR_STIMER0_COUNT, tick);
+       }
+
+       if (et.et_active) {
+               td = curthread;
+               td->td_intr_nesting_level++;
+               oldframe = td->td_intr_frame;
+               td->td_intr_frame = frame;
+               et.et_event_cb(&et, et.et_arg);
+               td->td_intr_frame = oldframe;
+               td->td_intr_nesting_level--;
+       }
+}
+
+void
+hv_et_init(void)
+{
+       et.et_name = "HyperV";
+       et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU | ET_FLAGS_PERIODIC;
+       et.et_quality = 1000;
+       et.et_frequency = HV_TIMER_FREQUENCY;
+       et.et_min_period = (1LL << 32) / HV_TIMER_FREQUENCY;
+       et.et_max_period = HV_MAX_DELTA_TICKS * ((1LL << 32) / 
HV_TIMER_FREQUENCY);
+       et.et_start = hv_et_start;
+       et.et_stop = hv_et_stop;
+       et.et_priv = &et;
+       et_register(&et);
+}
+

Modified: head/sys/dev/hyperv/vmbus/hv_hv.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_hv.c   Thu Jan 14 02:58:28 2016        
(r293872)
+++ head/sys/dev/hyperv/vmbus/hv_hv.c   Thu Jan 14 03:05:10 2016        
(r293873)
@@ -45,12 +45,6 @@ __FBSDID("$FreeBSD$");
 
 #include "hv_vmbus_priv.h"
 
-#define HV_X64_MSR_GUEST_OS_ID         0x40000000
-
-#define HV_X64_CPUID_MIN               0x40000005
-#define HV_X64_CPUID_MAX               0x4000ffff
-#define HV_X64_MSR_TIME_REF_COUNT      0x40000020
-
 #define HV_NANOSECONDS_PER_SEC         1000000000L
 
 
@@ -218,6 +212,8 @@ hv_vmbus_init(void) 
        hv_vmbus_g_context.hypercall_page = virt_addr;
 
        tc_init(&hv_timecounter); /* register virtual timecount */
+
+       hv_et_init();
        
        return (0);
 

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c    Thu Jan 14 02:58:28 
2016        (r293872)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c    Thu Jan 14 03:05:10 
2016        (r293873)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
+#include <sys/proc.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
@@ -153,7 +154,7 @@ handled:
  * message to process - an event or a channel message.
  */
 static inline int
-hv_vmbus_isr(void *unused) 
+hv_vmbus_isr(struct trapframe *frame)
 {
        int                             cpu;
        hv_vmbus_message*               msg;
@@ -193,11 +194,35 @@ hv_vmbus_isr(void *unused) 
        page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
        msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
 
+       /* we call eventtimer process the message */
+       if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
+               msg->header.message_type = HV_MESSAGE_TYPE_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
+                */
+               wmb();
+
+               if (msg->header.message_flags.u.message_pending) {
+                       /*
+                        * This will cause message queue rescan to possibly
+                        * deliver another msg from the hypervisor
+                        */
+                       wrmsr(HV_X64_MSR_EOM, 0);
+               }
+               hv_et_intr(frame);
+               return (FILTER_HANDLED);
+       }
+
        if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
                swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0);
        }
 
-       return FILTER_HANDLED;
+       return (FILTER_HANDLED);
 }
 
 #ifdef HV_DEBUG_INTR 
@@ -227,7 +252,7 @@ hv_vector_handler(struct trapframe *trap
        hv_intr_count++;
 #endif
 
-       hv_vmbus_isr(NULL); 
+       hv_vmbus_isr(trap_frame);
 
        /*
         * Enable preemption.

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Thu Jan 14 02:58:28 2016        
(r293872)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Thu Jan 14 03:05:10 2016        
(r293873)
@@ -359,11 +359,6 @@ typedef struct {
        struct sema                             control_sema;
 } hv_vmbus_connection;
 
-/*
- * Declare the MSR used to identify the guest OS
- */
-#define HV_X64_MSR_GUEST_OS_ID 0x40000000
-
 typedef union {
        uint64_t as_uint64_t;
        struct {
@@ -380,10 +375,6 @@ typedef union {
        } u;
 } hv_vmbus_x64_msr_guest_os_id_contents;
 
-/*
- *  Declare the MSR used to setup pages used to communicate with the hypervisor
- */
-#define HV_X64_MSR_HYPERCALL   0x40000001
 
 typedef union {
        uint64_t as_uint64_t;
@@ -513,6 +504,22 @@ typedef union {
 } hv_vmbus_synic_sint;
 
 /*
+ * Timer configuration register.
+ */
+union hv_timer_config {
+       uint64_t as_uint64;
+       struct {
+               uint64_t enable:1;
+               uint64_t periodic:1;
+               uint64_t lazy:1;
+               uint64_t auto_enable:1;
+               uint64_t reserved_z0:12;
+               uint64_t sintx:4;
+               uint64_t reserved_z1:44;
+       };
+};
+
+/*
  * Define syn_ic control register
  */
 typedef union _hv_vmbus_synic_scontrol {
@@ -542,8 +549,21 @@ typedef union {
        uint32_t        flags32[HV_EVENT_FLAGS_DWORD_COUNT];
 } hv_vmbus_synic_event_flags;
 
+#define HV_X64_CPUID_MIN       (0x40000005)
+#define HV_X64_CPUID_MAX       (0x4000ffff)
+
+/*
+ * Declare the MSR used to identify the guest OS
+ */
+#define HV_X64_MSR_GUEST_OS_ID (0x40000000)
+/*
+ *  Declare the MSR used to setup pages used to communicate with the hypervisor
+ */
+#define HV_X64_MSR_HYPERCALL   (0x40000001)
 /* MSR used to provide vcpu index */
-#define        HV_X64_MSR_VP_INDEX   (0x40000002)
+#define        HV_X64_MSR_VP_INDEX     (0x40000002)
+
+#define HV_X64_MSR_TIME_REF_COUNT      (0x40000020)
 
 /*
  * Define synthetic interrupt controller model specific registers
@@ -572,6 +592,18 @@ typedef union {
 #define HV_X64_MSR_SINT15     (0x4000009F)
 
 /*
+ * Synthetic Timer MSRs. Four timers per vcpu.
+ */
+#define HV_X64_MSR_STIMER0_CONFIG              0x400000B0
+#define HV_X64_MSR_STIMER0_COUNT               0x400000B1
+#define HV_X64_MSR_STIMER1_CONFIG              0x400000B2
+#define HV_X64_MSR_STIMER1_COUNT               0x400000B3
+#define HV_X64_MSR_STIMER2_CONFIG              0x400000B4
+#define HV_X64_MSR_STIMER2_COUNT               0x400000B5
+#define HV_X64_MSR_STIMER3_CONFIG              0x400000B6
+#define HV_X64_MSR_STIMER3_COUNT               0x400000B7
+
+/*
  * Declare the various hypercall operations
  */
 typedef enum {
@@ -678,6 +710,11 @@ int                        hv_vmbus_post_message(void 
*buffer
 int                    hv_vmbus_set_event(hv_vmbus_channel *channel);
 void                   hv_vmbus_on_events(void *);
 
+/**
+ * Event Timer interfaces
+ */
+void                   hv_et_init(void);
+void                   hv_et_intr(struct trapframe*);
 
 /*
  * The guest OS needs to register the guest ID with the hypervisor.

Modified: head/sys/modules/hyperv/vmbus/Makefile
==============================================================================
--- head/sys/modules/hyperv/vmbus/Makefile      Thu Jan 14 02:58:28 2016        
(r293872)
+++ head/sys/modules/hyperv/vmbus/Makefile      Thu Jan 14 03:05:10 2016        
(r293873)
@@ -7,6 +7,7 @@ KMOD=   hv_vmbus
 SRCS=  hv_channel.c \
        hv_channel_mgmt.c \
        hv_connection.c \
+       hv_et.c \
        hv_hv.c \
        hv_ring_buffer.c \
        hv_vmbus_drv_freebsd.c \
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to