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 <viremana@xxxxxxxxxxxxxxxxxxx> --- 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