@@ -278,9 +278,8 @@ void hv_hyp_synic_enable_regs(unsigned int cpu)
278278 union hv_synic_simp simp ;
279279 union hv_synic_siefp siefp ;
280280 union hv_synic_sint shared_sint ;
281- union hv_synic_scontrol sctrl ;
282281
283- /* Setup the Synic's message page */
282+ /* Setup the Synic's message page with the hypervisor. */
284283 simp .as_uint64 = hv_get_msr (HV_MSR_SIMP );
285284 simp .simp_enabled = 1 ;
286285
@@ -299,7 +298,7 @@ void hv_hyp_synic_enable_regs(unsigned int cpu)
299298
300299 hv_set_msr (HV_MSR_SIMP , simp .as_uint64 );
301300
302- /* Setup the Synic's event page */
301+ /* Setup the Synic's event page with the hypervisor. */
303302 siefp .as_uint64 = hv_get_msr (HV_MSR_SIEFP );
304303 siefp .siefp_enabled = 1 ;
305304
@@ -328,6 +327,11 @@ void hv_hyp_synic_enable_regs(unsigned int cpu)
328327 shared_sint .masked = false;
329328 shared_sint .auto_eoi = hv_recommend_using_aeoi ();
330329 hv_set_msr (HV_MSR_SINT0 + VMBUS_MESSAGE_SINT , shared_sint .as_uint64 );
330+ }
331+
332+ static void hv_hyp_synic_enable_interrupts (void )
333+ {
334+ union hv_synic_scontrol sctrl ;
331335
332336 /* Enable the global synic bit */
333337 sctrl .as_uint64 = hv_get_msr (HV_MSR_SCONTROL );
@@ -336,9 +340,59 @@ void hv_hyp_synic_enable_regs(unsigned int cpu)
336340 hv_set_msr (HV_MSR_SCONTROL , sctrl .as_uint64 );
337341}
338342
343+ static void hv_para_synic_enable_regs (unsigned int cpu )
344+ {
345+ union hv_synic_simp simp ;
346+ union hv_synic_siefp siefp ;
347+ struct hv_per_cpu_context * hv_cpu
348+ = per_cpu_ptr (hv_context .cpu_context , cpu );
349+
350+ /* Setup the Synic's message page with the paravisor. */
351+ simp .as_uint64 = hv_para_get_synic_register (HV_MSR_SIMP );
352+ simp .simp_enabled = 1 ;
353+ simp .base_simp_gpa = virt_to_phys (hv_cpu -> para_synic_message_page )
354+ >> HV_HYP_PAGE_SHIFT ;
355+ hv_para_set_synic_register (HV_MSR_SIMP , simp .as_uint64 );
356+
357+ /* Setup the Synic's event page with the paravisor. */
358+ siefp .as_uint64 = hv_para_get_synic_register (HV_MSR_SIEFP );
359+ siefp .siefp_enabled = 1 ;
360+ siefp .base_siefp_gpa = virt_to_phys (hv_cpu -> para_synic_event_page )
361+ >> HV_HYP_PAGE_SHIFT ;
362+ hv_para_set_synic_register (HV_MSR_SIEFP , siefp .as_uint64 );
363+ }
364+
365+ static void hv_para_synic_enable_interrupts (void )
366+ {
367+ union hv_synic_scontrol sctrl ;
368+
369+ /* Enable the global synic bit */
370+ sctrl .as_uint64 = hv_para_get_synic_register (HV_MSR_SCONTROL );
371+ sctrl .enable = 1 ;
372+ hv_para_set_synic_register (HV_MSR_SCONTROL , sctrl .as_uint64 );
373+ }
374+
339375int hv_synic_init (unsigned int cpu )
340376{
377+ if (vmbus_is_confidential ())
378+ hv_para_synic_enable_regs (cpu );
379+
380+ /*
381+ * The SINT is set in hv_hyp_synic_enable_regs() by calling
382+ * hv_set_msr(). hv_set_msr() in turn has special case code for the
383+ * SINT MSRs that write to the hypervisor version of the MSR *and*
384+ * the paravisor version of the MSR (but *without* the proxy bit when
385+ * VMBus is confidential).
386+ *
387+ * Then enable interrupts via the paravisor if VMBus is confidential,
388+ * and otherwise via the hypervisor.
389+ */
390+
341391 hv_hyp_synic_enable_regs (cpu );
392+ if (vmbus_is_confidential ())
393+ hv_para_synic_enable_interrupts ();
394+ else
395+ hv_hyp_synic_enable_interrupts ();
342396
343397 hv_stimer_legacy_init (cpu , VMBUS_MESSAGE_SINT );
344398
@@ -352,7 +406,6 @@ void hv_hyp_synic_disable_regs(unsigned int cpu)
352406 union hv_synic_sint shared_sint ;
353407 union hv_synic_simp simp ;
354408 union hv_synic_siefp siefp ;
355- union hv_synic_scontrol sctrl ;
356409
357410 shared_sint .as_uint64 = hv_get_msr (HV_MSR_SINT0 + VMBUS_MESSAGE_SINT );
358411
@@ -365,7 +418,7 @@ void hv_hyp_synic_disable_regs(unsigned int cpu)
365418
366419 simp .as_uint64 = hv_get_msr (HV_MSR_SIMP );
367420 /*
368- * In Isolation VM, sim and sief pages are allocated by
421+ * In Isolation VM, simp and sief pages are allocated by
369422 * paravisor. These pages also will be used by kdump
370423 * kernel. So just reset enable bit here and keep page
371424 * addresses.
@@ -395,14 +448,42 @@ void hv_hyp_synic_disable_regs(unsigned int cpu)
395448 }
396449
397450 hv_set_msr (HV_MSR_SIEFP , siefp .as_uint64 );
451+ }
452+
453+ static void hv_hyp_synic_disable_interrupts (void )
454+ {
455+ union hv_synic_scontrol sctrl ;
398456
399457 /* Disable the global synic bit */
400458 sctrl .as_uint64 = hv_get_msr (HV_MSR_SCONTROL );
401459 sctrl .enable = 0 ;
402460 hv_set_msr (HV_MSR_SCONTROL , sctrl .as_uint64 );
461+ }
403462
404- if (vmbus_irq != -1 )
405- disable_percpu_irq (vmbus_irq );
463+ static void hv_para_synic_disable_regs (unsigned int cpu )
464+ {
465+ union hv_synic_simp simp ;
466+ union hv_synic_siefp siefp ;
467+
468+ /* Disable SynIC's message page in the paravisor. */
469+ simp .as_uint64 = hv_para_get_synic_register (HV_MSR_SIMP );
470+ simp .simp_enabled = 0 ;
471+ hv_para_set_synic_register (HV_MSR_SIMP , simp .as_uint64 );
472+
473+ /* Disable SynIC's event page in the paravisor. */
474+ siefp .as_uint64 = hv_para_get_synic_register (HV_MSR_SIEFP );
475+ siefp .siefp_enabled = 0 ;
476+ hv_para_set_synic_register (HV_MSR_SIEFP , siefp .as_uint64 );
477+ }
478+
479+ static void hv_para_synic_disable_interrupts (void )
480+ {
481+ union hv_synic_scontrol sctrl ;
482+
483+ /* Disable the global synic bit */
484+ sctrl .as_uint64 = hv_para_get_synic_register (HV_MSR_SCONTROL );
485+ sctrl .enable = 0 ;
486+ hv_para_set_synic_register (HV_MSR_SCONTROL , sctrl .as_uint64 );
406487}
407488
408489#define HV_MAX_TRIES 3
@@ -415,16 +496,18 @@ void hv_hyp_synic_disable_regs(unsigned int cpu)
415496 * that the normal interrupt handling mechanism will find and process the channel interrupt
416497 * "very soon", and in the process clear the bit.
417498 */
418- static bool hv_synic_event_pending ( void )
499+ static bool __hv_synic_event_pending ( union hv_synic_event_flags * event , int sint )
419500{
420- struct hv_per_cpu_context * hv_cpu = this_cpu_ptr (hv_context .cpu_context );
421- union hv_synic_event_flags * event =
422- (union hv_synic_event_flags * )hv_cpu -> hyp_synic_event_page + VMBUS_MESSAGE_SINT ;
423- unsigned long * recv_int_page = event -> flags ; /* assumes VMBus version >= VERSION_WIN8 */
501+ unsigned long * recv_int_page ;
424502 bool pending ;
425503 u32 relid ;
426504 int tries = 0 ;
427505
506+ if (!event )
507+ return false;
508+
509+ event += sint ;
510+ recv_int_page = event -> flags ; /* assumes VMBus version >= VERSION_WIN8 */
428511retry :
429512 pending = false;
430513 for_each_set_bit (relid , recv_int_page , HV_EVENT_FLAGS_COUNT ) {
@@ -441,6 +524,17 @@ static bool hv_synic_event_pending(void)
441524 return pending ;
442525}
443526
527+ static bool hv_synic_event_pending (void )
528+ {
529+ struct hv_per_cpu_context * hv_cpu = this_cpu_ptr (hv_context .cpu_context );
530+ union hv_synic_event_flags * hyp_synic_event_page = hv_cpu -> hyp_synic_event_page ;
531+ union hv_synic_event_flags * para_synic_event_page = hv_cpu -> para_synic_event_page ;
532+
533+ return
534+ __hv_synic_event_pending (hyp_synic_event_page , VMBUS_MESSAGE_SINT ) ||
535+ __hv_synic_event_pending (para_synic_event_page , VMBUS_MESSAGE_SINT );
536+ }
537+
444538static int hv_pick_new_cpu (struct vmbus_channel * channel )
445539{
446540 int ret = - EBUSY ;
@@ -533,7 +627,27 @@ int hv_synic_cleanup(unsigned int cpu)
533627always_cleanup :
534628 hv_stimer_legacy_cleanup (cpu );
535629
630+ /*
631+ * First, disable the event and message pages
632+ * used for communicating with the host, and then
633+ * disable the host interrupts if VMBus is not
634+ * confidential.
635+ */
536636 hv_hyp_synic_disable_regs (cpu );
637+ if (!vmbus_is_confidential ())
638+ hv_hyp_synic_disable_interrupts ();
639+
640+ /*
641+ * Perform the same steps for the Confidential VMBus.
642+ * The sequencing provides the guarantee that no data
643+ * may be posted for processing before disabling interrupts.
644+ */
645+ if (vmbus_is_confidential ()) {
646+ hv_para_synic_disable_regs (cpu );
647+ hv_para_synic_disable_interrupts ();
648+ }
649+ if (vmbus_irq != -1 )
650+ disable_percpu_irq (vmbus_irq );
537651
538652 return ret ;
539653}
0 commit comments