Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Jun 2016 05:34:22 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r301583 - head/sys/dev/hyperv/vmbus
Message-ID:  <201606080534.u585YM1x063142@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Wed Jun  8 05:34:22 2016
New Revision: 301583
URL: https://svnweb.freebsd.org/changeset/base/301583

Log:
  hyperv/vmbus: Busdma-fy MNF and event flags.
  
  MFC after:	1 week
  Sponsored by:	Microsoft OSTC
  Differential Revision:	https://reviews.freebsd.org/D6744

Modified:
  head/sys/dev/hyperv/vmbus/hv_channel.c
  head/sys/dev/hyperv/vmbus/hv_connection.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  head/sys/dev/hyperv/vmbus/vmbus.c
  head/sys/dev/hyperv/vmbus/vmbus_var.h

Modified: head/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel.c	Wed Jun  8 05:32:39 2016	(r301582)
+++ head/sys/dev/hyperv/vmbus/hv_channel.c	Wed Jun  8 05:34:22 2016	(r301583)
@@ -62,17 +62,16 @@ static void	VmbusProcessChannelEvent(voi
 static void
 vmbus_channel_set_event(hv_vmbus_channel *channel)
 {
-	hv_vmbus_monitor_page *monitor_page;
-
 	if (channel->offer_msg.monitor_allocated) {
+		struct vmbus_softc *sc = vmbus_get_softc();
+		hv_vmbus_monitor_page *monitor_page;
+
 		/* Each uint32_t represents 32 channels */
 		synch_set_bit((channel->offer_msg.child_rel_id & 31),
-			((uint32_t *)hv_vmbus_g_connection.send_interrupt_page
+			((uint32_t *)sc->vmbus_tx_evtflags
 				+ ((channel->offer_msg.child_rel_id >> 5))));
 
-		monitor_page = (hv_vmbus_monitor_page *)
-			hv_vmbus_g_connection.monitor_page_2;
-
+		monitor_page = sc->vmbus_mnf2;
 		synch_set_bit(channel->monitor_bit,
 			(uint32_t *)&monitor_page->
 				trigger_group[channel->monitor_group].u.pending);

Modified: head/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c	Wed Jun  8 05:32:39 2016	(r301582)
+++ head/sys/dev/hyperv/vmbus/hv_connection.c	Wed Jun  8 05:34:22 2016	(r301583)
@@ -74,8 +74,8 @@ hv_vmbus_get_next_version(uint32_t curre
  * Negotiate the highest supported hypervisor version.
  */
 static int
-hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
-	uint32_t version)
+hv_vmbus_negotiate_version(struct vmbus_softc *sc,
+    hv_vmbus_channel_msg_info *msg_info, uint32_t version)
 {
 	int					ret = 0;
 	hv_vmbus_channel_initiate_contact	*msg;
@@ -86,14 +86,9 @@ hv_vmbus_negotiate_version(hv_vmbus_chan
 	msg->header.message_type = HV_CHANNEL_MESSAGE_INITIATED_CONTACT;
 	msg->vmbus_version_requested = version;
 
-	msg->interrupt_page = hv_get_phys_addr(
-		hv_vmbus_g_connection.interrupt_page);
-
-	msg->monitor_page_1 = hv_get_phys_addr(
-		hv_vmbus_g_connection.monitor_page_1);
-
-	msg->monitor_page_2 = hv_get_phys_addr(
-		hv_vmbus_g_connection.monitor_page_2);
+	msg->interrupt_page = sc->vmbus_evtflags_dma.hv_paddr;
+	msg->monitor_page_1 = sc->vmbus_mnf1_dma.hv_paddr;
+	msg->monitor_page_2 = sc->vmbus_mnf2_dma.hv_paddr;
 
 	/**
 	 * Add to list before we send the request since we may receive the
@@ -150,7 +145,7 @@ hv_vmbus_negotiate_version(hv_vmbus_chan
  * Send a connect request on the partition service connection
  */
 int
-hv_vmbus_connect(void)
+hv_vmbus_connect(struct vmbus_softc *sc)
 {
 	int					ret = 0;
 	uint32_t				version;
@@ -176,34 +171,6 @@ hv_vmbus_connect(void)
 	mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel",
 		NULL, MTX_DEF);
 
-	/**
-	 * Setup the vmbus event connection for channel interrupt abstraction
-	 * stuff
-	 */
-	hv_vmbus_g_connection.interrupt_page = malloc(
-					PAGE_SIZE, M_DEVBUF,
-					M_WAITOK | M_ZERO);
-
-	hv_vmbus_g_connection.recv_interrupt_page =
-		hv_vmbus_g_connection.interrupt_page;
-
-	hv_vmbus_g_connection.send_interrupt_page =
-		((uint8_t *) hv_vmbus_g_connection.interrupt_page +
-		    (PAGE_SIZE >> 1));
-
-	/**
-	 * Set up the monitor notification facility. The 1st page for
-	 * parent->child and the 2nd page for child->parent
-	 */
-	hv_vmbus_g_connection.monitor_page_1 = malloc(
-		PAGE_SIZE,
-		M_DEVBUF,
-		M_WAITOK | M_ZERO);
-	hv_vmbus_g_connection.monitor_page_2 = malloc(
-		PAGE_SIZE,
-		M_DEVBUF,
-		M_WAITOK | M_ZERO);
-
 	msg_info = (hv_vmbus_channel_msg_info*)
 		malloc(sizeof(hv_vmbus_channel_msg_info) +
 			sizeof(hv_vmbus_channel_initiate_contact),
@@ -217,7 +184,7 @@ hv_vmbus_connect(void)
 	version = HV_VMBUS_VERSION_CURRENT;
 
 	do {
-		ret = hv_vmbus_negotiate_version(msg_info, version);
+		ret = hv_vmbus_negotiate_version(sc, msg_info, version);
 		if (ret == EWOULDBLOCK) {
 			/*
 			 * We timed out.
@@ -251,14 +218,6 @@ hv_vmbus_connect(void)
 	mtx_destroy(&hv_vmbus_g_connection.channel_lock);
 	mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
 
-	if (hv_vmbus_g_connection.interrupt_page != NULL) {
-		free(hv_vmbus_g_connection.interrupt_page, M_DEVBUF);
-		hv_vmbus_g_connection.interrupt_page = NULL;
-	}
-
-	free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF);
-	free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF);
-
 	if (msg_info) {
 		sema_destroy(&msg_info->wait_sema);
 		free(msg_info, M_DEVBUF);
@@ -281,8 +240,6 @@ hv_vmbus_disconnect(void)
 
 	ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload));
 
-	free(hv_vmbus_g_connection.interrupt_page, M_DEVBUF);
-
 	mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
 
 	free(hv_vmbus_g_connection.channels, M_DEVBUF);
@@ -343,14 +300,13 @@ vmbus_event_proc(struct vmbus_softc *sc,
 }
 
 void
-vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu)
+vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu)
 {
 	struct vmbus_evtflags *eventf;
 
 	eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
 	if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) {
-		vmbus_event_flags_proc(
-		    hv_vmbus_g_connection.recv_interrupt_page,
+		vmbus_event_flags_proc(sc->vmbus_rx_evtflags,
 		    VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT);
 	}
 }
@@ -395,14 +351,14 @@ int hv_vmbus_post_message(void *buffer, 
 int
 hv_vmbus_set_event(hv_vmbus_channel *channel)
 {
+	struct vmbus_softc *sc = vmbus_get_softc();
 	int ret = 0;
 	uint32_t child_rel_id = channel->offer_msg.child_rel_id;
 
 	/* Each uint32_t represents 32 channels */
 
 	synch_set_bit(child_rel_id & 31,
-		(((uint32_t *)hv_vmbus_g_connection.send_interrupt_page
-			+ (child_rel_id >> 5))));
+		(((uint32_t *)sc->vmbus_tx_evtflags + (child_rel_id >> 5))));
 	ret = hv_vmbus_signal_event(channel->signal_event_param);
 
 	return (ret);

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Wed Jun  8 05:32:39 2016	(r301582)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Wed Jun  8 05:34:22 2016	(r301583)
@@ -244,25 +244,7 @@ typedef enum {
 typedef struct {
 	hv_vmbus_connect_state			connect_state;
 	uint32_t				next_gpadl_handle;
-	/**
-	 * Represents channel interrupts. Each bit position
-	 * represents a channel.
-	 * When a channel sends an interrupt via VMBUS, it
-	 * finds its bit in the send_interrupt_page, set it and
-	 * calls Hv to generate a port event. The other end
-	 * receives the port event and parse the
-	 * recv_interrupt_page to see which bit is set
-	 */
-	void					*interrupt_page;
-	void					*send_interrupt_page;
-	void					*recv_interrupt_page;
-	/*
-	 * 2 pages - 1st page for parent->child
-	 * notification and 2nd is child->parent
-	 * notification
-	 */
-	void					*monitor_page_1;
-	void					*monitor_page_2;
+
 	TAILQ_HEAD(, hv_vmbus_channel_msg_info)	channel_msg_anchor;
 	struct mtx				channel_msg_lock;
 	/**
@@ -440,7 +422,8 @@ int			hv_vmbus_child_device_unregister(
 /**
  * Connection interfaces
  */
-int			hv_vmbus_connect(void);
+struct vmbus_softc;
+int			hv_vmbus_connect(struct vmbus_softc *);
 int			hv_vmbus_disconnect(void);
 int			hv_vmbus_post_message(void *buffer, size_t buf_size);
 int			hv_vmbus_set_event(hv_vmbus_channel *channel);

Modified: head/sys/dev/hyperv/vmbus/vmbus.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus.c	Wed Jun  8 05:32:39 2016	(r301582)
+++ head/sys/dev/hyperv/vmbus/vmbus.c	Wed Jun  8 05:34:22 2016	(r301583)
@@ -309,30 +309,50 @@ vmbus_synic_teardown(void *arg)
 static int
 vmbus_dma_alloc(struct vmbus_softc *sc)
 {
+	bus_dma_tag_t parent_dtag;
+	uint8_t *evtflags;
 	int cpu;
 
+	parent_dtag = bus_get_dma_tag(sc->vmbus_dev);
 	CPU_FOREACH(cpu) {
 		void *ptr;
 
 		/*
 		 * Per-cpu messages and event flags.
 		 */
-		ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
-		    PAGE_SIZE, 0, PAGE_SIZE,
-		    VMBUS_PCPU_PTR(sc, message_dma, cpu),
+		ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+		    PAGE_SIZE, VMBUS_PCPU_PTR(sc, message_dma, cpu),
 		    BUS_DMA_WAITOK | BUS_DMA_ZERO);
 		if (ptr == NULL)
 			return ENOMEM;
 		VMBUS_PCPU_GET(sc, message, cpu) = ptr;
 
-		ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
-		    PAGE_SIZE, 0, PAGE_SIZE,
-		    VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
+		ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+		    PAGE_SIZE, VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
 		    BUS_DMA_WAITOK | BUS_DMA_ZERO);
 		if (ptr == NULL)
 			return ENOMEM;
 		VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr;
 	}
+
+	evtflags = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+	    PAGE_SIZE, &sc->vmbus_evtflags_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+	if (evtflags == NULL)
+		return ENOMEM;
+	sc->vmbus_rx_evtflags = (u_long *)evtflags;
+	sc->vmbus_tx_evtflags = evtflags + (PAGE_SIZE / 2);
+	sc->vmbus_evtflags = evtflags;
+
+	sc->vmbus_mnf1 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+	    PAGE_SIZE, &sc->vmbus_mnf1_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+	if (sc->vmbus_mnf1 == NULL)
+		return ENOMEM;
+
+	sc->vmbus_mnf2 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+	    PAGE_SIZE, &sc->vmbus_mnf2_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+	if (sc->vmbus_mnf2 == NULL)
+		return ENOMEM;
+
 	return 0;
 }
 
@@ -341,6 +361,21 @@ vmbus_dma_free(struct vmbus_softc *sc)
 {
 	int cpu;
 
+	if (sc->vmbus_evtflags != NULL) {
+		hyperv_dmamem_free(&sc->vmbus_evtflags_dma, sc->vmbus_evtflags);
+		sc->vmbus_evtflags = NULL;
+		sc->vmbus_rx_evtflags = NULL;
+		sc->vmbus_tx_evtflags = NULL;
+	}
+	if (sc->vmbus_mnf1 != NULL) {
+		hyperv_dmamem_free(&sc->vmbus_mnf1_dma, sc->vmbus_mnf1);
+		sc->vmbus_mnf1 = NULL;
+	}
+	if (sc->vmbus_mnf2 != NULL) {
+		hyperv_dmamem_free(&sc->vmbus_mnf2_dma, sc->vmbus_mnf2);
+		sc->vmbus_mnf2 = NULL;
+	}
+
 	CPU_FOREACH(cpu) {
 		if (VMBUS_PCPU_GET(sc, message, cpu) != NULL) {
 			hyperv_dmamem_free(
@@ -609,8 +644,7 @@ vmbus_bus_init(void)
 	/*
 	 * Connect to VMBus in the root partition
 	 */
-	ret = hv_vmbus_connect();
-
+	ret = hv_vmbus_connect(sc);
 	if (ret != 0)
 		goto cleanup;
 

Modified: head/sys/dev/hyperv/vmbus/vmbus_var.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_var.h	Wed Jun  8 05:32:39 2016	(r301582)
+++ head/sys/dev/hyperv/vmbus/vmbus_var.h	Wed Jun  8 05:34:22 2016	(r301583)
@@ -51,7 +51,7 @@ struct vmbus_pcpu_data {
 	struct vmbus_message	*message;	/* shared messages */
 	uint32_t		vcpuid;		/* virtual cpuid */
 	int			event_flags_cnt;/* # of event flags */
-	struct vmbus_evtflags	*event_flags;	/* shared event flags */
+	struct vmbus_evtflags	*event_flags;	/* event flags from host */
 
 	/* Rarely used fields */
 	struct hyperv_dma	message_dma;	/* busdma glue */
@@ -63,12 +63,26 @@ struct vmbus_pcpu_data {
 
 struct vmbus_softc {
 	void			(*vmbus_event_proc)(struct vmbus_softc *, int);
+	void			*vmbus_tx_evtflags;
+						/* event flags to host */
+	void			*vmbus_mnf2;	/* monitored by host */
+
+	u_long			*vmbus_rx_evtflags;
+						/* compat evtflgs from host */
 	struct vmbus_pcpu_data	vmbus_pcpu[MAXCPU];
 
 	/* Rarely used fields */
 	device_t		vmbus_dev;
 	int			vmbus_idtvec;
 	uint32_t		vmbus_flags;	/* see VMBUS_FLAG_ */
+
+	/* Shared memory for vmbus_{rx,tx}_evtflags */
+	void			*vmbus_evtflags;
+	struct hyperv_dma	vmbus_evtflags_dma;
+
+	void			*vmbus_mnf1;	/* monitored by VM, unused */
+	struct hyperv_dma	vmbus_mnf1_dma;
+	struct hyperv_dma	vmbus_mnf2_dma;
 };
 
 #define VMBUS_FLAG_ATTACHED	0x0001	/* vmbus was attached */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606080534.u585YM1x063142>