Page MenuHomeFreeBSD

D4676.diff
No OneTemporary

D4676.diff

Index: head/sys/conf/files.amd64
===================================================================
--- head/sys/conf/files.amd64
+++ head/sys/conf/files.amd64
@@ -273,6 +273,7 @@
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
Index: head/sys/conf/files.i386
===================================================================
--- head/sys/conf/files.i386
+++ head/sys/conf/files.i386
@@ -247,6 +247,7 @@
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
Index: head/sys/dev/hyperv/vmbus/hv_et.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_et.c
+++ head/sys/dev/hyperv/vmbus/hv_et.c
@@ -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);
+}
+
Index: head/sys/dev/hyperv/vmbus/hv_hv.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_hv.c
+++ head/sys/dev/hyperv/vmbus/hv_hv.c
@@ -45,12 +45,6 @@
#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_g_context.hypercall_page = virt_addr;
tc_init(&hv_timecounter); /* register virtual timecount */
+
+ hv_et_init();
return (0);
Index: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -38,6 +38,7 @@
#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 @@
* 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 @@
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_intr_count++;
#endif
- hv_vmbus_isr(NULL);
+ hv_vmbus_isr(trap_frame);
/*
* Enable preemption.
Index: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -359,11 +359,6 @@
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 @@
} 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 @@
} 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 @@
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 @@
#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_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.
Index: head/sys/modules/hyperv/vmbus/Makefile
===================================================================
--- head/sys/modules/hyperv/vmbus/Makefile
+++ head/sys/modules/hyperv/vmbus/Makefile
@@ -7,6 +7,7 @@
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 \

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 18, 1:12 PM (2 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23881218
Default Alt Text
D4676.diff (10 KB)

Event Timeline