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.
Doorbell events are delivered by a SynIC interrupt. Configure a SynIC
interrupt source for doorbell.
Signed-off-by: Vineeth Pillai <[email protected]>
---
drivers/hv/hv_synic.c | 30 +++++++++++++++++++++++++-----
include/asm-generic/hyperv-tlfs.h | 15 ++++++++++++++-
2 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/hv/hv_synic.c b/drivers/hv/hv_synic.c
index a2f712acca82..6a00c66edc3f 100644
--- a/drivers/hv/hv_synic.c
+++ b/drivers/hv/hv_synic.c
@@ -112,6 +112,15 @@ void mshv_isr(void)
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
}
+static inline bool hv_recommend_using_aeoi(void)
+{
+#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
+ return !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
+#else
+ return false;
+#endif
+}
+
int mshv_synic_init(unsigned int cpu)
{
union hv_synic_simp simp;
@@ -166,14 +175,19 @@ int mshv_synic_init(unsigned int cpu)
sint.as_uint64 = 0;
sint.vector = HYPERVISOR_CALLBACK_VECTOR;
sint.masked = false;
-#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
- sint.auto_eoi = !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
-#else
- sint.auto_eoi = 0;
-#endif
+ sint.auto_eoi = hv_recommend_using_aeoi();
hv_set_register(HV_REGISTER_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX,
sint.as_uint64);
+ /* Doorbell SINT */
+ sint.as_uint64 = 0;
+ sint.vector = HYPERVISOR_CALLBACK_VECTOR;
+ sint.masked = false;
+ sint.as_intercept = 1;
+ sint.auto_eoi = hv_recommend_using_aeoi();
+ hv_set_register(HV_REGISTER_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
+ sint.as_uint64);
+
/* Enable global synic bit */
sctrl.as_uint64 = hv_get_register(HV_REGISTER_SCONTROL);
sctrl.enable = 1;
@@ -221,6 +235,12 @@ int mshv_synic_cleanup(unsigned int cpu)
hv_set_register(HV_REGISTER_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX,
sint.as_uint64);
+ /* Disable Doorbell SINT */
+ sint.as_uint64 = hv_get_register(HV_REGISTER_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX);
+ sint.masked = true;
+ hv_set_register(HV_REGISTER_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
+ sint.as_uint64);
+
/* Disable Synic's event ring page */
sirbp.as_uint64 = hv_get_register(HV_REGISTER_SIRBP);
sirbp.sirbp_enabled = false;
diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
index 42e0237b0da8..3ed4f532ed57 100644
--- a/include/asm-generic/hyperv-tlfs.h
+++ b/include/asm-generic/hyperv-tlfs.h
@@ -262,6 +262,9 @@ enum hv_status {
#define HV_SYNIC_HVL_SHARED_SINT_INDEX 0x00000004
#define HV_SYNIC_FIRST_UNUSED_SINT_INDEX 0x00000005
+/* mshv assigned SINT for doorbell */
+#define HV_SYNIC_DOORBELL_SINT_INDEX HV_SYNIC_FIRST_UNUSED_SINT_INDEX
+
#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0)
#define HV_SYNIC_SIMP_ENABLE (1ULL << 0)
#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0)
@@ -284,6 +287,14 @@ struct hv_timer_message_payload {
__u64 delivery_time; /* When the message was delivered */
} __packed;
+/*
+ * Message format for notifications delivered via
+ * intercept message(as_intercept=1)
+ */
+struct hv_notification_message_payload {
+ u32 sint_index;
+} __packed;
+
/* Define the synthentic interrupt controller event ring format */
#define HV_SYNIC_EVENT_RING_MESSAGE_COUNT 63
@@ -350,7 +361,9 @@ union hv_synic_sint {
u64 masked:1;
u64 auto_eoi:1;
u64 polling:1;
- u64 reserved2:45;
+ u64 as_intercept: 1;
+ u64 proxy: 1;
+ u64 reserved2:43;
} __packed;
};
--
2.25.1