All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vineeth Pillai <viremana@linux.microsoft.com>
To: Nuno Das Neves <nunodasneves@linux.microsoft.com>,
	Wei Liu <wei.liu@kernel.org>,
	Sunil Muthuswamy <sunilmut@microsoft.com>,
	Michael Kelley <mikelley@microsoft.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>
Cc: Vineeth Pillai <viremana@linux.microsoft.com>,
	"K. Y. Srinivasan" <kys@microsoft.com>,
	virtualization@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org, linux-hyperv@vger.kernel.org
Subject: [PATCH 05/17] mshv: SynIC event ring and event flags support
Date: Wed,  2 Jun 2021 17:20:50 +0000	[thread overview]
Message-ID: <b0231e97ba26fede0d1f31acca488f5461340d74.1622654100.git.viremana@linux.microsoft.com> (raw)
In-Reply-To: <cover.1622654100.git.viremana@linux.microsoft.com>

Doorbell is a  mechanism by which a parent partition can register for
notification if a specified mmio address is touched by a child partition.
Parent partition can setup the notification by specifying mmio address,
size of the data written(1/2/4/8 bytes) and optionally the data as well.

Hyper-V makes use of an event ring buffer to signal events. This
buffer is implemented as a GPA overlay page. Doorbell notifications are
delivered via this event ring buffer.

Enable SynIC event ring buffer.

While at it, enable SynIC event flags. It is a lightweight inter-partition
communication mechanism to signal events between partitions or from
hypervisor to a partition.

Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
---
 arch/x86/include/asm/hyperv-tlfs.h |  2 +
 drivers/hv/hv_synic.c              | 81 +++++++++++++++++++++++++++---
 drivers/hv/mshv_main.c             |  6 +--
 include/asm-generic/hyperv-tlfs.h  | 29 +++++++++++
 include/linux/mshv.h               |  8 ++-
 5 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index 871f5d014ae0..e4b0eea1703e 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -189,6 +189,7 @@ enum hv_isolation_type {
 #define HV_REGISTER_SIEFP			0x40000082
 #define HV_REGISTER_SIMP			0x40000083
 #define HV_REGISTER_EOM				0x40000084
+#define HV_REGISTER_SIRBP			0x40000085
 #define HV_REGISTER_SINT0			0x40000090
 #define HV_REGISTER_SINT1			0x40000091
 #define HV_REGISTER_SINT2			0x40000092
@@ -252,6 +253,7 @@ enum hv_isolation_type {
 #define HV_X64_MSR_SIEFP		HV_REGISTER_SIEFP
 #define HV_X64_MSR_VP_INDEX		HV_REGISTER_VP_INDEX
 #define HV_X64_MSR_EOM			HV_REGISTER_EOM
+#define HV_X64_MSR_SIRBP		HV_REGISTER_SIRBP
 #define HV_X64_MSR_SINT0		HV_REGISTER_SINT0
 #define HV_X64_MSR_SINT15		HV_REGISTER_SINT15
 #define HV_X64_MSR_CRASH_P0		HV_REGISTER_CRASH_P0
diff --git a/drivers/hv/hv_synic.c b/drivers/hv/hv_synic.c
index 9800ae6693a9..a2f712acca82 100644
--- a/drivers/hv/hv_synic.c
+++ b/drivers/hv/hv_synic.c
@@ -19,8 +19,8 @@
 
 void mshv_isr(void)
 {
-	struct hv_message_page **msg_page =
-			this_cpu_ptr(mshv.synic_message_page);
+	struct hv_synic_pages *spages = this_cpu_ptr(mshv.synic_pages);
+	struct hv_message_page **msg_page = &spages->synic_message_page;
 	struct hv_message *msg;
 	u32 message_type;
 	struct mshv_partition *partition;
@@ -115,10 +115,16 @@ void mshv_isr(void)
 int mshv_synic_init(unsigned int cpu)
 {
 	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	union hv_synic_sirbp sirbp;
 	union hv_synic_sint sint;
 	union hv_synic_scontrol sctrl;
-	struct hv_message_page **msg_page =
-			this_cpu_ptr(mshv.synic_message_page);
+	struct hv_synic_pages *spages = this_cpu_ptr(mshv.synic_pages);
+	struct hv_message_page **msg_page = &spages->synic_message_page;
+	struct hv_synic_event_flags_page **event_flags_page =
+			&spages->synic_event_flags_page;
+	struct hv_synic_event_ring_page **event_ring_page =
+			&spages->synic_event_ring_page;
 
 	/* Setup the Synic's message page */
 	simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
@@ -127,11 +133,35 @@ int mshv_synic_init(unsigned int cpu)
 			     HV_HYP_PAGE_SIZE,
                              MEMREMAP_WB);
 	if (!(*msg_page)) {
-		pr_err("%s: memremap failed\n", __func__);
+		pr_err("%s: SIMP memremap failed\n", __func__);
 		return -EFAULT;
 	}
 	hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
 
+	/* Setup the Synic's event flags page */
+	siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
+	siefp.siefp_enabled = true;
+	*event_flags_page = memremap(siefp.base_siefp_gpa << PAGE_SHIFT,
+		     PAGE_SIZE, MEMREMAP_WB);
+
+	if (!(*event_flags_page)) {
+		pr_err("%s: SIEFP memremap failed\n", __func__);
+		goto cleanup;
+	}
+	hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
+
+	/* Setup the Synic's event ring page */
+	sirbp.as_uint64 = hv_get_register(HV_REGISTER_SIRBP);
+	sirbp.sirbp_enabled = true;
+	*event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
+		     PAGE_SIZE, MEMREMAP_WB);
+
+	if (!(*event_ring_page)) {
+		pr_err("%s: SIRBP memremap failed\n", __func__);
+		goto cleanup;
+	}
+	hv_set_register(HV_REGISTER_SIRBP, sirbp.as_uint64);
+
 	/* Enable intercepts */
 	sint.as_uint64 = 0;
 	sint.vector = HYPERVISOR_CALLBACK_VECTOR;
@@ -150,15 +180,40 @@ int mshv_synic_init(unsigned int cpu)
 	hv_set_register(HV_REGISTER_SCONTROL, sctrl.as_uint64);
 
 	return 0;
+
+cleanup:
+	if (*event_ring_page) {
+		sirbp.sirbp_enabled = false;
+		hv_set_register(HV_REGISTER_SIRBP, sirbp.as_uint64);
+		memunmap(*event_ring_page);
+	}
+	if (*event_flags_page) {
+		siefp.siefp_enabled = false;
+		hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
+		memunmap(*event_flags_page);
+	}
+	if (*msg_page) {
+		simp.simp_enabled = false;
+		hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
+		memunmap(*msg_page);
+	}
+
+	return -EFAULT;
 }
 
 int mshv_synic_cleanup(unsigned int cpu)
 {
 	union hv_synic_sint sint;
 	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	union hv_synic_sirbp sirbp;
 	union hv_synic_scontrol sctrl;
-	struct hv_message_page **msg_page =
-			this_cpu_ptr(mshv.synic_message_page);
+	struct hv_synic_pages *spages = this_cpu_ptr(mshv.synic_pages);
+	struct hv_message_page **msg_page = &spages->synic_message_page;
+	struct hv_synic_event_flags_page **event_flags_page =
+		&spages->synic_event_flags_page;
+	struct hv_synic_event_ring_page **event_ring_page =
+		&spages->synic_event_ring_page;
 
 	/* Disable the interrupt */
 	sint.as_uint64 = hv_get_register(HV_REGISTER_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX);
@@ -166,6 +221,18 @@ int mshv_synic_cleanup(unsigned int cpu)
 	hv_set_register(HV_REGISTER_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX,
 			sint.as_uint64);
 
+	/* Disable Synic's event ring page */
+	sirbp.as_uint64 = hv_get_register(HV_REGISTER_SIRBP);
+	sirbp.sirbp_enabled = false;
+	hv_set_register(HV_REGISTER_SIRBP, sirbp.as_uint64);
+	memunmap(*event_ring_page);
+
+	/* Disable Synic's event flags page */
+	siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
+	siefp.siefp_enabled = false;
+	hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
+	memunmap(*event_flags_page);
+
 	/* Disable Synic's message page */
 	simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
 	simp.simp_enabled = false;
diff --git a/drivers/hv/mshv_main.c b/drivers/hv/mshv_main.c
index fe6fb2668d36..2adae676dba5 100644
--- a/drivers/hv/mshv_main.c
+++ b/drivers/hv/mshv_main.c
@@ -1118,8 +1118,8 @@ __init mshv_init(void)
 		return ret;
 	}
 
-	mshv.synic_message_page = alloc_percpu(struct hv_message_page *);
-	if (!mshv.synic_message_page) {
+	mshv.synic_pages = alloc_percpu(struct hv_synic_pages);
+	if (!mshv.synic_pages) {
 		pr_err("%s: failed to allocate percpu synic page\n", __func__);
 		misc_deregister(&mshv_dev);
 		return -ENOMEM;
@@ -1144,7 +1144,7 @@ static void
 __exit mshv_exit(void)
 {
 	cpuhp_remove_state(mshv_cpuhp_online);
-	free_percpu(mshv.synic_message_page);
+	free_percpu(mshv.synic_pages);
 
 	misc_deregister(&mshv_dev);
 }
diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
index 8f08d0e9163d..f70391a3320f 100644
--- a/include/asm-generic/hyperv-tlfs.h
+++ b/include/asm-generic/hyperv-tlfs.h
@@ -279,8 +279,23 @@ struct hv_timer_message_payload {
 	__u64 delivery_time;	/* When the message was delivered */
 } __packed;
 
+/* Define the synthentic interrupt controller event ring format */
+#define HV_SYNIC_EVENT_RING_MESSAGE_COUNT 63
+
+struct hv_synic_event_ring {
+	u8  signal_masked;
+	u8  ring_full;
+	u16 reserved_z;
+	u32 data[HV_SYNIC_EVENT_RING_MESSAGE_COUNT];
+} __packed;
+
+struct hv_synic_event_ring_page {
+	volatile struct hv_synic_event_ring sint_event_ring[HV_SYNIC_SINT_COUNT];
+};
+
 /* Define synthetic interrupt controller flag constants. */
 #define HV_EVENT_FLAGS_COUNT		(256 * 8)
+#define HV_EVENT_FLAGS_BYTE_COUNT	(256)
 #define HV_EVENT_FLAGS_LONG_COUNT	(256 / sizeof(unsigned long))
 
 /*
@@ -304,9 +319,14 @@ union hv_stimer_config {
 
 /* Define the synthetic interrupt controller event flags format. */
 union hv_synic_event_flags {
+	unsigned char flags8[HV_EVENT_FLAGS_BYTE_COUNT];
 	unsigned long flags[HV_EVENT_FLAGS_LONG_COUNT];
 };
 
+struct hv_synic_event_flags_page {
+	volatile union hv_synic_event_flags event_flags[HV_SYNIC_SINT_COUNT];
+};
+
 /* Define SynIC control register. */
 union hv_synic_scontrol {
 	u64 as_uint64;
@@ -349,6 +369,15 @@ union hv_synic_siefp {
 	} __packed;
 };
 
+union hv_synic_sirbp {
+	u64 as_uint64;
+	struct {
+		u64 sirbp_enabled:1;
+		u64 preserved:11;
+		u64 base_sirbp_gpa:52;
+	} __packed;
+};
+
 struct hv_vpset {
 	u64 format;
 	u64 valid_bank_mask;
diff --git a/include/linux/mshv.h b/include/linux/mshv.h
index 33f4d0cfee11..679aa3fa8cdb 100644
--- a/include/linux/mshv.h
+++ b/include/linux/mshv.h
@@ -49,8 +49,14 @@ struct mshv_partition {
 	} vps;
 };
 
+struct hv_synic_pages {
+	struct hv_message_page *synic_message_page;
+	struct hv_synic_event_flags_page *synic_event_flags_page;
+	struct hv_synic_event_ring_page *synic_event_ring_page;
+};
+
 struct mshv {
-	struct hv_message_page __percpu **synic_message_page;
+	struct hv_synic_pages __percpu *synic_pages;
 	struct {
 		spinlock_t lock;
 		u64 count;
-- 
2.25.1


  parent reply	other threads:[~2021-06-02 17:21 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-02 17:20 [PATCH 00/17] irqfd and ioeventfd support for mshv Vineeth Pillai
2021-06-02 17:20 ` [PATCH 01/17] hyperv: Few TLFS definitions Vineeth Pillai
2021-06-02 17:20 ` [PATCH 02/17] drivers: hv: vmbus: Use TLFS definition for VMBUS_MESSAGE_SINT Vineeth Pillai
2021-06-02 17:20 ` [PATCH 03/17] acpi: export node_to_pxm Vineeth Pillai
2021-06-02 17:20 ` [PATCH 04/17] hyperv: Wrapper for setting proximity_domain_info Vineeth Pillai
2021-06-02 17:20 ` Vineeth Pillai [this message]
2021-06-02 17:20 ` [PATCH 06/17] mshv: SynIC port and connection hypercalls Vineeth Pillai
2021-06-10 12:19   ` Vitaly Kuznetsov
2021-06-10 12:19     ` Vitaly Kuznetsov
2021-06-29 12:55     ` Wei Liu
2021-06-29 16:19       ` Vineeth Pillai
2021-06-29 13:06   ` Wei Liu
2021-06-29 16:21     ` Vineeth Pillai
2021-06-30 10:44   ` Wei Liu
2021-06-30 11:10   ` Wei Liu
2021-06-30 15:03     ` Vineeth Pillai
2021-06-02 17:20 ` [PATCH 07/17] hyperv: Configure SINT for Doorbell Vineeth Pillai
2021-06-02 17:20 ` [PATCH 08/17] mshv: Port id management Vineeth Pillai
2021-06-02 17:20 ` [PATCH 09/17] mshv: Doorbell handler in hypercall ISR Vineeth Pillai
2021-06-02 17:20 ` [PATCH 10/17] mshv: Doorbell register/unregister API Vineeth Pillai
2021-06-02 17:20 ` [PATCH 11/17] mshv: HvClearVirtualInterrupt hypercall Vineeth Pillai
2021-06-02 17:20 ` [PATCH 12/17] mshv: Add irqfd support for mshv Vineeth Pillai
2021-06-02 17:20 ` [PATCH 13/17] mshv: Add ioeventfd " Vineeth Pillai
2021-06-02 17:20 ` [PATCH 14/17] mshv: Notifier framework for EOI for level triggered interrupts Vineeth Pillai
2021-06-02 17:21 ` [PATCH 15/17] mshv: Level-triggered interrupt support for irqfd Vineeth Pillai
2021-06-02 17:21 ` [PATCH 16/17] mshv: User space controlled MSI irq routing for mshv Vineeth Pillai
2021-06-02 17:21 ` [PATCH 17/17] mshv: Use in kernel MSI routing for irqfd Vineeth Pillai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b0231e97ba26fede0d1f31acca488f5461340d74.1622654100.git.viremana@linux.microsoft.com \
    --to=viremana@linux.microsoft.com \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mikelley@microsoft.com \
    --cc=nunodasneves@linux.microsoft.com \
    --cc=sunilmut@microsoft.com \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=vkuznets@redhat.com \
    --cc=wei.liu@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.