Drivers: hv: vmbus: Implement a clockevent device
Subsystems (2)
PATCH v4 1/1 Drivers: hv: vmbus: Implement a clockevent device
Implement a clockevent device based on the timer support available on Hyper-V.
In this version of the patch I have addressed Jason's review comments.
Signed-off-by K. Y. Srinivasan <[email protected]>
Reviewed-by Jason Wang <[email protected]>
--- arch/x86/include/uapi/asm/hyperv.h | 11 +++++ drivers/hv/hv.c | 78 ++++++++++++++++++++++++++++++++++++ drivers/hv/hyperv_vmbus.h | 21 ++++++++++ drivers/hv/vmbus_drv.c | 37 ++++++++++++++++- 4 files changed, 145 insertions(+), 2 deletions(-)
arch/x86/include/uapi/asm/hyperv.h +11 -0
@@ -187,6 +187,17 @@#define HV_X64_MSR_SINT14 0x4000009E#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#define HV_X64_MSR_HYPERCALL_ENABLE 0x00000001#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT 12
drivers/hv/hv.c +78 -0
125 lines not on this page · raw message
drivers/hv/hyperv_vmbus.h +21 -0
@@ -178,6 +178,23 @@ struct hv_message_header { }; }; +/* +* Timer configuration register. +*/ +union hv_timer_config { +u64 as_uint64; +struct { +u64 enable:1 ; +u64 periodic:1 ; +u64 lazy:1 ; +u64 auto_enable:1 ; +u64 reserved_z0:12 ; +u64 sintx:4 ; +u64 reserved_z1:44 ; + }; +}; + +/* Define timer message payload structure. */ struct hv_timer_message_payload {u32 timer_index;
@@ -519,6 +536,10 @@ struct hv_context {* buffer to post messages to the host. */ void *post_msg_page[NR_CPUS ]; +/* +* Support PV clockevent device. +*/ +struct clock_event_device *clk_evt[NR_CPUS ]; };extern struct hv_context hv_context;
drivers/hv/vmbus_drv.c +35 -2
@@ -32,6 +32,7 @@#include <linux/completion.h> #include <linux/hyperv.h> #include <linux/kernel_stat.h> +#include <linux/clockchips.h> #include <asm/hyperv.h> #include <asm/hypervisor.h> #include <asm/mshyperv.h>
@@ -578,6 +579,34 @@ static void vmbus_onmessage_work(struct work_struct *work)kfree (ctx); } +void hv_process_timer_expiration (struct hv_message *msg,int cpu) +{ +struct clock_event_device *dev = hv_context.clk_evt[cpu]; + +if (dev->event_handler) + dev->event_handler (dev); + + msg->header.message_type =HVMSG_NONE ; + +/* +* Make sure the write to MessageType (ie set to +* HVMSG_NONE) happens before we read the +* MessagePending and EOMing. Otherwise, the EOMing +* will not deliver any more messages since there is +* no empty slot +*/ +mb (); + +if (msg->header.message_flags.msg_pending) { +/* +* This will cause message queue rescan to +* possibly deliver another msg from the +* hypervisor +*/ +wrmsrl (HV_X64_MSR_EOM ,0 ); + } +} +static void vmbus_on_msg_dpc (unsigned long data) {int cpu =smp_processor_id ();
@@ -667,8 +696,12 @@ static void vmbus_isr(void) msg = (struct hv_message *)page_addr +VMBUS_MESSAGE_SINT ;/* Check if there are actual msgs to be processed */ -if (msg->header.message_type !=HVMSG_NONE ) -tasklet_schedule (&msg_dpc); +if (msg->header.message_type !=HVMSG_NONE ) { +if (msg->header.message_type ==HVMSG_TIMER_EXPIRED ) +hv_process_timer_expiration (msg, cpu); +else +tasklet_schedule (&msg_dpc); + } }/*
Signature · 1 line
1.7.4.1