iPXE
hyperv.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * Hyper-V driver
29  *
30  */
31 
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <assert.h>
37 #include <errno.h>
38 #include <byteswap.h>
39 #include <pic8259.h>
40 #include <ipxe/malloc.h>
41 #include <ipxe/device.h>
42 #include <ipxe/timer.h>
43 #include <ipxe/quiesce.h>
44 #include <ipxe/cpuid.h>
45 #include <ipxe/msr.h>
46 #include <ipxe/hyperv.h>
47 #include <ipxe/vmbus.h>
48 #include "hyperv.h"
49 
50 /** Maximum time to wait for a message response
51  *
52  * This is a policy decision.
53  */
54 #define HV_MESSAGE_MAX_WAIT_MS 1000
55 
56 /** Hyper-V timer frequency (fixed 10Mhz) */
57 #define HV_TIMER_HZ 10000000
58 
59 /** Hyper-V timer scale factor (used to avoid 64-bit division) */
60 #define HV_TIMER_SHIFT 18
61 
62 /**
63  * Convert a Hyper-V status code to an iPXE status code
64  *
65  * @v status Hyper-V status code
66  * @ret rc iPXE status code (before negation)
67  */
68 #define EHV( status ) EPLATFORM ( EINFO_EPLATFORM, (status) )
69 
70 /**
71  * Allocate zeroed pages
72  *
73  * @v hv Hyper-V hypervisor
74  * @v ... Page addresses to fill in, terminated by NULL
75  * @ret rc Return status code
76  */
77 __attribute__ (( sentinel )) int
78 hv_alloc_pages ( struct hv_hypervisor *hv, ... ) {
79  va_list args;
80  void **page;
81  int i;
82 
83  /* Allocate and zero pages */
84  va_start ( args, hv );
85  for ( i = 0 ; ( ( page = va_arg ( args, void ** ) ) != NULL ); i++ ) {
86  *page = malloc_phys ( PAGE_SIZE, PAGE_SIZE );
87  if ( ! *page )
88  goto err_alloc;
89  memset ( *page, 0, PAGE_SIZE );
90  }
91  va_end ( args );
92 
93  return 0;
94 
95  err_alloc:
96  va_end ( args );
97  va_start ( args, hv );
98  for ( ; i >= 0 ; i-- ) {
99  page = va_arg ( args, void ** );
100  free_phys ( *page, PAGE_SIZE );
101  }
102  va_end ( args );
103  return -ENOMEM;
104 }
105 
106 /**
107  * Free pages
108  *
109  * @v hv Hyper-V hypervisor
110  * @v ... Page addresses, terminated by NULL
111  */
112 __attribute__ (( sentinel )) void
113 hv_free_pages ( struct hv_hypervisor *hv, ... ) {
114  va_list args;
115  void *page;
116 
117  va_start ( args, hv );
118  while ( ( page = va_arg ( args, void * ) ) != NULL )
119  free_phys ( page, PAGE_SIZE );
120  va_end ( args );
121 }
122 
123 /**
124  * Allocate message buffer
125  *
126  * @v hv Hyper-V hypervisor
127  * @ret rc Return status code
128  */
129 static int hv_alloc_message ( struct hv_hypervisor *hv ) {
130 
131  /* Allocate buffer. Must be aligned to at least 8 bytes and
132  * must not cross a page boundary, so align on its own size.
133  */
134  hv->message = malloc_phys ( sizeof ( *hv->message ),
135  sizeof ( *hv->message ) );
136  if ( ! hv->message )
137  return -ENOMEM;
138 
139  return 0;
140 }
141 
142 /**
143  * Free message buffer
144  *
145  * @v hv Hyper-V hypervisor
146  */
147 static void hv_free_message ( struct hv_hypervisor *hv ) {
148 
149  /* Free buffer */
150  free_phys ( hv->message, sizeof ( *hv->message ) );
151 }
152 
153 /**
154  * Check whether or not we are running in Hyper-V
155  *
156  * @ret rc Return status code
157  */
158 static int hv_check_hv ( void ) {
159  struct x86_features features;
160  uint32_t interface_id;
161  uint32_t discard_ebx;
164 
165  /* Check for presence of a hypervisor (not necessarily Hyper-V) */
166  x86_features ( &features );
167  if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_HYPERVISOR ) ) {
168  DBGC ( HV_INTERFACE_ID, "HV not running in a hypervisor\n" );
169  return -ENODEV;
170  }
171 
172  /* Check that hypervisor is Hyper-V */
173  cpuid ( HV_CPUID_INTERFACE_ID, 0, &interface_id, &discard_ebx,
175  if ( interface_id != HV_INTERFACE_ID ) {
176  DBGC ( HV_INTERFACE_ID, "HV not running in Hyper-V (interface "
177  "ID %#08x)\n", interface_id );
178  return -ENODEV;
179  }
180 
181  return 0;
182 }
183 
184 /**
185  * Check required features
186  *
187  * @v hv Hyper-V hypervisor
188  * @ret rc Return status code
189  */
190 static int hv_check_features ( struct hv_hypervisor *hv ) {
191  uint32_t available;
192  uint32_t permissions;
195 
196  /* Check that required features and privileges are available */
197  cpuid ( HV_CPUID_FEATURES, 0, &available, &permissions, &discard_ecx,
198  &discard_edx );
199  if ( ! ( available & HV_FEATURES_AVAIL_HYPERCALL_MSR ) ) {
200  DBGC ( hv, "HV %p has no hypercall MSRs (features %08x:%08x)\n",
201  hv, available, permissions );
202  return -ENODEV;
203  }
204  if ( ! ( available & HV_FEATURES_AVAIL_SYNIC_MSR ) ) {
205  DBGC ( hv, "HV %p has no SynIC MSRs (features %08x:%08x)\n",
206  hv, available, permissions );
207  return -ENODEV;
208  }
209  if ( ! ( permissions & HV_FEATURES_PERM_POST_MESSAGES ) ) {
210  DBGC ( hv, "HV %p cannot post messages (features %08x:%08x)\n",
211  hv, available, permissions );
212  return -EACCES;
213  }
214  if ( ! ( permissions & HV_FEATURES_PERM_SIGNAL_EVENTS ) ) {
215  DBGC ( hv, "HV %p cannot signal events (features %08x:%08x)",
216  hv, available, permissions );
217  return -EACCES;
218  }
219 
220  return 0;
221 }
222 
223 /**
224  * Check that Gen 2 UEFI firmware is not running
225  *
226  * @v hv Hyper-V hypervisor
227  * @ret rc Return status code
228  *
229  * We must not steal ownership from the Gen 2 UEFI firmware, since
230  * doing so will cause an immediate crash. Avoid this by checking for
231  * the guest OS identity known to be used by the Gen 2 UEFI firmware.
232  */
233 static int hv_check_uefi ( struct hv_hypervisor *hv ) {
234  uint64_t guest_os_id;
235 
236  /* Check for UEFI firmware's guest OS identity */
237  guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID );
238  if ( guest_os_id == HV_GUEST_OS_ID_UEFI ) {
239  DBGC ( hv, "HV %p is owned by UEFI firmware\n", hv );
240  return -ENOTSUP;
241  }
242 
243  return 0;
244 }
245 
246 /**
247  * Map hypercall page
248  *
249  * @v hv Hyper-V hypervisor
250  */
251 static void hv_map_hypercall ( struct hv_hypervisor *hv ) {
252  union {
253  struct {
254  uint32_t ebx;
255  uint32_t ecx;
256  uint32_t edx;
257  } __attribute__ (( packed ));
258  char text[ 13 /* "bbbbccccdddd" + NUL */ ];
259  } vendor_id;
260  uint32_t build;
262  uint32_t discard_eax;
265  uint64_t guest_os_id;
267 
268  /* Report guest OS identity */
269  guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID );
270  if ( guest_os_id != 0 ) {
271  DBGC ( hv, "HV %p guest OS ID MSR was %#08llx\n",
272  hv, guest_os_id );
273  }
274  guest_os_id = HV_GUEST_OS_ID_IPXE;
275  DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
276  wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id );
277 
278  /* Get hypervisor system identity (for debugging) */
279  cpuid ( HV_CPUID_VENDOR_ID, 0, &discard_eax, &vendor_id.ebx,
280  &vendor_id.ecx, &vendor_id.edx );
281  vendor_id.text[ sizeof ( vendor_id.text ) - 1 ] = '\0';
283  &discard_edx );
284  DBGC ( hv, "HV %p detected \"%s\" version %d.%d build %d\n", hv,
285  vendor_id.text, ( version >> 16 ), ( version & 0xffff ), build );
286 
287  /* Map hypercall page */
288  hypercall = rdmsr ( HV_X64_MSR_HYPERCALL );
289  hypercall &= ( PAGE_SIZE - 1 );
291  DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall );
292  wrmsr ( HV_X64_MSR_HYPERCALL, hypercall );
293 }
294 
295 /**
296  * Unmap hypercall page
297  *
298  * @v hv Hyper-V hypervisor
299  */
300 static void hv_unmap_hypercall ( struct hv_hypervisor *hv ) {
302  uint64_t guest_os_id;
303 
304  /* Unmap the hypercall page */
305  hypercall = rdmsr ( HV_X64_MSR_HYPERCALL );
306  hypercall &= ( ( PAGE_SIZE - 1 ) & ~HV_HYPERCALL_ENABLE );
307  DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall );
308  wrmsr ( HV_X64_MSR_HYPERCALL, hypercall );
309 
310  /* Reset the guest OS identity */
311  guest_os_id = 0;
312  DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
313  wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id );
314 }
315 
316 /**
317  * Map synthetic interrupt controller
318  *
319  * @v hv Hyper-V hypervisor
320  */
321 static void hv_map_synic ( struct hv_hypervisor *hv ) {
322  uint64_t simp;
323  uint64_t siefp;
324  uint64_t scontrol;
325 
326  /* Zero SynIC message and event pages */
327  memset ( hv->synic.message, 0, PAGE_SIZE );
328  memset ( hv->synic.event, 0, PAGE_SIZE );
329 
330  /* Map SynIC message page */
331  simp = rdmsr ( HV_X64_MSR_SIMP );
332  simp &= ( PAGE_SIZE - 1 );
333  simp |= ( virt_to_phys ( hv->synic.message ) | HV_SIMP_ENABLE );
334  DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp );
335  wrmsr ( HV_X64_MSR_SIMP, simp );
336 
337  /* Map SynIC event page */
338  siefp = rdmsr ( HV_X64_MSR_SIEFP );
339  siefp &= ( PAGE_SIZE - 1 );
340  siefp |= ( virt_to_phys ( hv->synic.event ) | HV_SIEFP_ENABLE );
341  DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp );
342  wrmsr ( HV_X64_MSR_SIEFP, siefp );
343 
344  /* Enable SynIC */
345  scontrol = rdmsr ( HV_X64_MSR_SCONTROL );
346  scontrol |= HV_SCONTROL_ENABLE;
347  DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
348  wrmsr ( HV_X64_MSR_SCONTROL, scontrol );
349 }
350 
351 /**
352  * Unmap synthetic interrupt controller, leaving SCONTROL untouched
353  *
354  * @v hv Hyper-V hypervisor
355  */
356 static void hv_unmap_synic_no_scontrol ( struct hv_hypervisor *hv ) {
357  uint64_t siefp;
358  uint64_t simp;
359 
360  /* Unmap SynIC event page */
361  siefp = rdmsr ( HV_X64_MSR_SIEFP );
362  siefp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIEFP_ENABLE );
363  DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp );
364  wrmsr ( HV_X64_MSR_SIEFP, siefp );
365 
366  /* Unmap SynIC message page */
367  simp = rdmsr ( HV_X64_MSR_SIMP );
368  simp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIMP_ENABLE );
369  DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp );
370  wrmsr ( HV_X64_MSR_SIMP, simp );
371 }
372 
373 /**
374  * Unmap synthetic interrupt controller
375  *
376  * @v hv Hyper-V hypervisor
377  */
378 static void hv_unmap_synic ( struct hv_hypervisor *hv ) {
379  uint64_t scontrol;
380 
381  /* Disable SynIC */
382  scontrol = rdmsr ( HV_X64_MSR_SCONTROL );
383  scontrol &= ~HV_SCONTROL_ENABLE;
384  DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
385  wrmsr ( HV_X64_MSR_SCONTROL, scontrol );
386 
387  /* Unmap SynIC event and message pages */
389 }
390 
391 /**
392  * Enable synthetic interrupt
393  *
394  * @v hv Hyper-V hypervisor
395  * @v sintx Synthetic interrupt number
396  */
397 void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) {
398  unsigned long msr = HV_X64_MSR_SINT ( sintx );
399  uint64_t sint;
400 
401  /* Enable synthetic interrupt
402  *
403  * We have to enable the interrupt, otherwise messages will
404  * not be delivered (even though the documentation implies
405  * that polling for messages is possible). We enable AutoEOI
406  * and hook the interrupt to the obsolete IRQ13 (FPU
407  * exception) vector, which will be implemented as a no-op.
408  */
409  sint = rdmsr ( msr );
410  sint &= ~( HV_SINT_MASKED | HV_SINT_VECTOR_MASK );
411  sint |= ( HV_SINT_AUTO_EOI |
412  HV_SINT_VECTOR ( IRQ_INT ( 13 /* See comment above */ ) ) );
413  DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
414  wrmsr ( msr, sint );
415 }
416 
417 /**
418  * Disable synthetic interrupt
419  *
420  * @v hv Hyper-V hypervisor
421  * @v sintx Synthetic interrupt number
422  */
423 void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) {
424  unsigned long msr = HV_X64_MSR_SINT ( sintx );
425  uint64_t sint;
426 
427  /* Do nothing if interrupt is already disabled */
428  sint = rdmsr ( msr );
429  if ( sint & HV_SINT_MASKED )
430  return;
431 
432  /* Disable synthetic interrupt */
433  sint &= ~HV_SINT_AUTO_EOI;
434  sint |= HV_SINT_MASKED;
435  DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
436  wrmsr ( msr, sint );
437 }
438 
439 /**
440  * Post message
441  *
442  * @v hv Hyper-V hypervisor
443  * @v id Connection ID
444  * @v type Message type
445  * @v data Message
446  * @v len Length of message
447  * @ret rc Return status code
448  */
449 int hv_post_message ( struct hv_hypervisor *hv, unsigned int id,
450  unsigned int type, const void *data, size_t len ) {
451  struct hv_post_message *msg = &hv->message->posted;
452  int status;
453  int rc;
454 
455  /* Sanity check */
456  assert ( len <= sizeof ( msg->data ) );
457 
458  /* Construct message */
459  memset ( msg, 0, sizeof ( *msg ) );
460  msg->id = cpu_to_le32 ( id );
461  msg->type = cpu_to_le32 ( type );
462  msg->len = cpu_to_le32 ( len );
463  memcpy ( msg->data, data, len );
464  DBGC2 ( hv, "HV %p connection %d posting message type %#08x:\n",
465  hv, id, type );
466  DBGC2_HDA ( hv, 0, msg->data, len );
467 
468  /* Post message */
469  if ( ( status = hv_call ( hv, HV_POST_MESSAGE, msg, NULL ) ) != 0 ) {
470  rc = -EHV ( status );
471  DBGC ( hv, "HV %p could not post message to %#08x: %s\n",
472  hv, id, strerror ( rc ) );
473  return rc;
474  }
475 
476  return 0;
477 }
478 
479 /**
480  * Wait for received message
481  *
482  * @v hv Hyper-V hypervisor
483  * @v sintx Synthetic interrupt number
484  * @ret rc Return status code
485  */
486 int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx ) {
487  struct hv_message *msg = &hv->message->received;
488  struct hv_message *src = &hv->synic.message[sintx];
489  unsigned int retries;
490  size_t len;
491 
492  /* Wait for message to arrive */
493  for ( retries = 0 ; retries < HV_MESSAGE_MAX_WAIT_MS ; retries++ ) {
494 
495  /* Check for message */
496  if ( src->type ) {
497 
498  /* Copy message */
499  memset ( msg, 0, sizeof ( *msg ) );
500  len = src->len;
501  assert ( len <= sizeof ( *msg ) );
502  memcpy ( msg, src,
503  ( offsetof ( typeof ( *msg ), data ) + len ) );
504  DBGC2 ( hv, "HV %p SINT%d received message type "
505  "%#08x:\n", hv, sintx,
506  le32_to_cpu ( msg->type ) );
507  DBGC2_HDA ( hv, 0, msg->data, len );
508 
509  /* Consume message */
510  src->type = 0;
511 
512  return 0;
513  }
514 
515  /* Trigger message delivery */
516  wrmsr ( HV_X64_MSR_EOM, 0 );
517 
518  /* Delay */
519  mdelay ( 1 );
520  }
521 
522  DBGC ( hv, "HV %p SINT%d timed out waiting for message\n",
523  hv, sintx );
524  return -ETIMEDOUT;
525 }
526 
527 /**
528  * Signal event
529  *
530  * @v hv Hyper-V hypervisor
531  * @v id Connection ID
532  * @v flag Flag number
533  * @ret rc Return status code
534  */
535 int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id,
536  unsigned int flag ) {
537  struct hv_signal_event *event = &hv->message->signalled;
538  int status;
539  int rc;
540 
541  /* Construct event */
542  memset ( event, 0, sizeof ( *event ) );
543  event->id = cpu_to_le32 ( id );
544  event->flag = cpu_to_le16 ( flag );
545 
546  /* Signal event */
547  if ( ( status = hv_call ( hv, HV_SIGNAL_EVENT, event, NULL ) ) != 0 ) {
548  rc = -EHV ( status );
549  DBGC ( hv, "HV %p could not signal event to %#08x: %s\n",
550  hv, id, strerror ( rc ) );
551  return rc;
552  }
553 
554  return 0;
555 }
556 
557 /**
558  * Probe root device
559  *
560  * @v rootdev Root device
561  * @ret rc Return status code
562  */
563 static int hv_probe ( struct root_device *rootdev ) {
564  struct hv_hypervisor *hv;
565  int rc;
566 
567  /* Check we are running in Hyper-V */
568  if ( ( rc = hv_check_hv() ) != 0 )
569  goto err_check_hv;
570 
571  /* Allocate and initialise structure */
572  hv = zalloc ( sizeof ( *hv ) );
573  if ( ! hv ) {
574  rc = -ENOMEM;
575  goto err_alloc;
576  }
577 
578  /* Check features */
579  if ( ( rc = hv_check_features ( hv ) ) != 0 )
580  goto err_check_features;
581 
582  /* Check that Gen 2 UEFI firmware is not running */
583  if ( ( rc = hv_check_uefi ( hv ) ) != 0 )
584  goto err_check_uefi;
585 
586  /* Allocate pages */
587  if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message,
588  &hv->synic.event, NULL ) ) != 0 )
589  goto err_alloc_pages;
590 
591  /* Allocate message buffer */
592  if ( ( rc = hv_alloc_message ( hv ) ) != 0 )
593  goto err_alloc_message;
594 
595  /* Map hypercall page */
596  hv_map_hypercall ( hv );
597 
598  /* Map synthetic interrupt controller */
599  hv_map_synic ( hv );
600 
601  /* Probe Hyper-V devices */
602  if ( ( rc = vmbus_probe ( hv, &rootdev->dev ) ) != 0 )
603  goto err_vmbus_probe;
604 
605  rootdev_set_drvdata ( rootdev, hv );
606  return 0;
607 
608  vmbus_remove ( hv, &rootdev->dev );
609  err_vmbus_probe:
610  hv_unmap_synic ( hv );
611  hv_unmap_hypercall ( hv );
612  hv_free_message ( hv );
613  err_alloc_message:
614  hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
615  NULL );
616  err_alloc_pages:
617  err_check_uefi:
618  err_check_features:
619  free ( hv );
620  err_alloc:
621  err_check_hv:
622  return rc;
623 }
624 
625 /**
626  * Remove root device
627  *
628  * @v rootdev Root device
629  */
630 static void hv_remove ( struct root_device *rootdev ) {
631  struct hv_hypervisor *hv = rootdev_get_drvdata ( rootdev );
632 
633  vmbus_remove ( hv, &rootdev->dev );
634  hv_unmap_synic ( hv );
635  hv_unmap_hypercall ( hv );
636  hv_free_message ( hv );
637  hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
638  NULL );
639  free ( hv );
640  rootdev_set_drvdata ( rootdev, NULL );
641 }
642 
643 /** Hyper-V root device driver */
644 static struct root_driver hv_root_driver = {
645  .probe = hv_probe,
646  .remove = hv_remove,
647 };
648 
649 /** Hyper-V root device */
650 struct root_device hv_root_device __root_device = {
651  .dev = { .name = "Hyper-V" },
652  .driver = &hv_root_driver,
653 };
654 
655 /**
656  * Quiesce system
657  *
658  */
659 static void hv_quiesce ( void ) {
660  struct hv_hypervisor *hv = rootdev_get_drvdata ( &hv_root_device );
661  unsigned int i;
662 
663  /* Do nothing if we are not running in Hyper-V */
664  if ( ! hv )
665  return;
666 
667  /* The "enlightened" portions of the Windows Server 2016 boot
668  * process will not cleanly take ownership of an active
669  * Hyper-V connection. Experimentation shows that the minimum
670  * requirement is that we disable the SynIC message page
671  * (i.e. zero the SIMP MSR).
672  *
673  * We cannot perform a full shutdown of the Hyper-V
674  * connection. Experimentation shows that if we disable the
675  * SynIC (i.e. zero the SCONTROL MSR) then Windows Server 2016
676  * will enter an indefinite wait loop.
677  *
678  * Attempt to create a safe handover environment by resetting
679  * all MSRs except for SCONTROL.
680  *
681  * Note that we do not shut down our VMBus devices, since we
682  * may need to unquiesce the system and continue operation.
683  */
684 
685  /* Disable all synthetic interrupts */
686  for ( i = 0 ; i <= HV_SINT_MAX ; i++ )
687  hv_disable_sint ( hv, i );
688 
689  /* Unmap synthetic interrupt controller, leaving SCONTROL
690  * enabled (see above).
691  */
693 
694  /* Unmap hypercall page */
695  hv_unmap_hypercall ( hv );
696 
697  DBGC ( hv, "HV %p quiesced\n", hv );
698 }
699 
700 /**
701  * Unquiesce system
702  *
703  */
704 static void hv_unquiesce ( void ) {
705  struct hv_hypervisor *hv = rootdev_get_drvdata ( &hv_root_device );
706  uint64_t simp;
707  int rc;
708 
709  /* Do nothing if we are not running in Hyper-V */
710  if ( ! hv )
711  return;
712 
713  /* Experimentation shows that the "enlightened" portions of
714  * Windows Server 2016 will break our Hyper-V connection at
715  * some point during a SAN boot. Surprisingly it does not
716  * change the guest OS ID MSR, but it does leave the SynIC
717  * message page disabled.
718  *
719  * Our own explicit quiescing procedure will also disable the
720  * SynIC message page. We can therefore use the SynIC message
721  * page enable bit as a heuristic to determine when we need to
722  * reestablish our Hyper-V connection.
723  */
724  simp = rdmsr ( HV_X64_MSR_SIMP );
725  if ( simp & HV_SIMP_ENABLE )
726  return;
727 
728  /* Remap hypercall page */
729  hv_map_hypercall ( hv );
730 
731  /* Remap synthetic interrupt controller */
732  hv_map_synic ( hv );
733 
734  /* Reset Hyper-V devices */
735  if ( ( rc = vmbus_reset ( hv, &hv_root_device.dev ) ) != 0 ) {
736  DBGC ( hv, "HV %p could not unquiesce: %s\n",
737  hv, strerror ( rc ) );
738  /* Nothing we can do */
739  return;
740  }
741 }
742 
743 /** Hyper-V quiescer */
744 struct quiescer hv_quiescer __quiescer = {
745  .quiesce = hv_quiesce,
746  .unquiesce = hv_unquiesce,
747 };
748 
749 /**
750  * Probe timer
751  *
752  * @ret rc Return status code
753  */
754 static int hv_timer_probe ( void ) {
755  uint32_t available;
756  uint32_t discard_ebx;
759  int rc;
760 
761  /* Check we are running in Hyper-V */
762  if ( ( rc = hv_check_hv() ) != 0 )
763  return rc;
764 
765  /* Check for available reference counter */
766  cpuid ( HV_CPUID_FEATURES, 0, &available, &discard_ebx, &discard_ecx,
767  &discard_edx );
768  if ( ! ( available & HV_FEATURES_AVAIL_TIME_REF_COUNT_MSR ) ) {
769  DBGC ( HV_INTERFACE_ID, "HV has no time reference counter\n" );
770  return -ENODEV;
771  }
772 
773  return 0;
774 }
775 
776 /**
777  * Get current system time in ticks
778  *
779  * @ret ticks Current time, in ticks
780  */
781 static unsigned long hv_currticks ( void ) {
782 
783  /* Calculate time using a combination of bit shifts and
784  * multiplication (to avoid a 64-bit division).
785  */
786  return ( ( rdmsr ( HV_X64_MSR_TIME_REF_COUNT ) >> HV_TIMER_SHIFT ) *
788 }
789 
790 /**
791  * Delay for a fixed number of microseconds
792  *
793  * @v usecs Number of microseconds for which to delay
794  */
795 static void hv_udelay ( unsigned long usecs ) {
796  uint32_t start;
797  uint32_t elapsed;
798  uint32_t threshold;
799 
800  /* Spin until specified number of 10MHz ticks have elapsed */
801  start = rdmsr ( HV_X64_MSR_TIME_REF_COUNT );
802  threshold = ( usecs * ( HV_TIMER_HZ / 1000000 ) );
803  do {
804  elapsed = ( rdmsr ( HV_X64_MSR_TIME_REF_COUNT ) - start );
805  } while ( elapsed < threshold );
806 }
807 
808 /** Hyper-V timer */
809 struct timer hv_timer __timer ( TIMER_PREFERRED ) = {
810  .name = "Hyper-V",
811  .probe = hv_timer_probe,
812  .currticks = hv_currticks,
813  .udelay = hv_udelay,
814 };
815 
816 /* Drag in objects via hv_root_device */
817 REQUIRING_SYMBOL ( hv_root_device );
818 
819 /* Drag in netvsc driver */
820 REQUIRE_OBJECT ( netvsc );
static void hv_map_hypercall(struct hv_hypervisor *hv)
Map hypercall page.
Definition: hyperv.c:251
#define __attribute__(x)
Definition: compiler.h:10
#define HV_FEATURES_AVAIL_TIME_REF_COUNT_MSR
Time reference counter MSR is available.
Definition: hyperv.h:25
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define va_end(ap)
Definition: stdarg.h:9
#define TICKS_PER_SEC
Number of ticks per second.
Definition: timer.h:15
static void rootdev_set_drvdata(struct root_device *rootdev, void *priv)
Set root device driver-private data.
Definition: device.h:140
#define HV_X64_MSR_SIEFP
SynIC event flags page MSR.
Definition: hyperv.h:52
static int hv_probe(struct root_device *rootdev)
Probe root device.
Definition: hyperv.c:563
#define le32_to_cpu(value)
Definition: byteswap.h:113
int hv_wait_for_message(struct hv_hypervisor *hv, unsigned int sintx)
Wait for received message.
Definition: hyperv.c:486
static int hv_alloc_message(struct hv_hypervisor *hv)
Allocate message buffer.
Definition: hyperv.c:129
Error codes.
A quiescer.
Definition: quiesce.h:15
int hv_post_message(struct hv_hypervisor *hv, unsigned int id, unsigned int type, const void *data, size_t len)
Post message.
Definition: hyperv.c:449
#define HV_FEATURES_PERM_SIGNAL_EVENTS
Guest may signal events.
Definition: hyperv.h:37
static void hv_unmap_synic(struct hv_hypervisor *hv)
Unmap synthetic interrupt controller.
Definition: hyperv.c:378
#define HV_HYPERCALL_ENABLE
Enable hypercall page.
Definition: hyperv.h:48
static void const void * src
Definition: crypto.h:244
#define DBGC(...)
Definition: compiler.h:505
int hv_signal_event(struct hv_hypervisor *hv, unsigned int id, unsigned int flag)
Signal event.
Definition: hyperv.c:535
int vmbus_reset(struct hv_hypervisor *hv, struct device *parent)
Reset Hyper-V virtual machine bus.
Definition: vmbus.c:1426
char name[40]
Name.
Definition: device.h:75
A root device.
Definition: device.h:94
#define HV_X64_MSR_SIMP
SynIC message page MSR.
Definition: hyperv.h:55
unsigned long long uint64_t
Definition: stdint.h:13
static void *__malloc malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition: malloc.h:62
#define HV_TIMER_SHIFT
Hyper-V timer scale factor (used to avoid 64-bit division)
Definition: hyperv.c:60
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition: cpuid.c:163
struct hv_event * event
Event flag page.
Definition: hyperv.h:189
void * hypercall
Hypercall page.
Definition: hyperv.h:205
iPXE timers
struct timer hv_timer __timer(TIMER_PREFERRED)
Hyper-V timer.
#define EACCES
Permission denied.
Definition: errno.h:298
A signalled event.
Definition: hyperv.h:119
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
x86 CPU features
Definition: cpuid.h:23
Hyper-V driver.
#define PAGE_SIZE
Page size.
Definition: io.h:27
static unsigned int hypercall
Definition: xen.h:42
static void hv_quiesce(void)
Quiesce system.
Definition: hyperv.c:659
struct device dev
Device chain.
Definition: device.h:99
static int hv_timer_probe(void)
Probe timer.
Definition: hyperv.c:754
#define HV_X64_MSR_SCONTROL
SynIC control MSR.
Definition: hyperv.h:49
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
static unsigned long hv_currticks(void)
Get current system time in ticks.
Definition: hyperv.c:781
#define HV_SINT_MAX
Maximum synthetic interrupt number.
Definition: hyperv.h:72
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
static void hv_unmap_hypercall(struct hv_hypervisor *hv)
Unmap hypercall page.
Definition: hyperv.c:300
Dynamic memory allocation.
A timer.
Definition: timer.h:28
REQUIRE_OBJECT(netvsc)
uint32_t start
Starting offset.
Definition: netvsc.h:12
Hyper-V virtual machine bus.
static void hv_free_message(struct hv_hypervisor *hv)
Free message buffer.
Definition: hyperv.c:147
#define HV_TIMER_HZ
Hyper-V timer frequency (fixed 10Mhz)
Definition: hyperv.c:57
uint8_t status
Status.
Definition: ena.h:16
Hyper-V interface.
void vmbus_remove(struct hv_hypervisor *hv, struct device *parent)
Remove Hyper-V virtual machine bus.
Definition: vmbus.c:1458
struct hv_message received
Received message.
Definition: hyperv.h:197
#define ENOMEM
Not enough space.
Definition: errno.h:534
uint8_t vendor_id[3]
Definition: ib_mad.h:22
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define HV_FEATURES_AVAIL_HYPERCALL_MSR
Hypercall MSRs are available.
Definition: hyperv.h:31
REQUIRING_SYMBOL(hv_root_device)
#define va_arg(ap, type)
Definition: stdarg.h:8
#define HV_POST_MESSAGE
Post message.
Definition: hyperv.h:75
static uint32_t uint32_t uint32_t * ebx
Definition: cpuid.h:86
#define HV_X64_MSR_GUEST_OS_ID
Guest OS identity MSR.
Definition: hyperv.h:40
Quiesce system.
#define HV_CPUID_VENDOR_ID
Get vendor identification.
Definition: hyperv.h:13
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void hv_unquiesce(void)
Unquiesce system.
Definition: hyperv.c:704
int hv_alloc_pages(struct hv_hypervisor *hv,...)
Allocate zeroed pages.
Definition: hyperv.c:78
struct hv_signal_event signalled
Signalled event.
Definition: hyperv.h:199
#define CPUID_FEATURES_INTEL_ECX_HYPERVISOR
Hypervisor is present.
Definition: cpuid.h:46
#define HV_FEATURES_AVAIL_SYNIC_MSR
SynIC MSRs are available.
Definition: hyperv.h:28
#define TIMER_PREFERRED
Preferred timer.
Definition: timer.h:62
void(* quiesce)(void)
Quiesce system.
Definition: quiesce.h:17
uint32_t discard_edx
Definition: hyperv.h:32
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define DBGC2_HDA(...)
Definition: compiler.h:523
A received message.
Definition: hyperv.h:100
#define HV_INTERFACE_ID
Hyper-V interface identification.
Definition: hyperv.h:16
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define HV_SIGNAL_EVENT
Signal event.
Definition: hyperv.h:116
static uint32_t uint32_t uint32_t uint32_t * ecx
Definition: cpuid.h:86
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
x86 CPU feature detection
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
struct hv_message * message
Message page.
Definition: hyperv.h:187
#define HV_X64_MSR_SINT(x)
SynIC interrupt source MSRs.
Definition: hyperv.h:61
#define HV_CPUID_FEATURES
Get hypervisor features.
Definition: hyperv.h:22
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
Definition: hyperv.c:113
#define HV_FEATURES_PERM_POST_MESSAGES
Guest may post messages.
Definition: hyperv.h:34
uint32_t features
Supported features.
Definition: ena.h:16
#define HV_X64_MSR_TIME_REF_COUNT
Time reference MSR.
Definition: hyperv.h:46
#define IRQ_INT(irq)
Definition: pic8259.h:60
A root device driver.
Definition: device.h:107
static uint32_t uint32_t uint32_t uint32_t uint32_t * edx
Definition: cpuid.h:87
#define ENODEV
No such device.
Definition: errno.h:509
uint32_t discard_ecx
Definition: hyperv.h:31
A posted message.
Definition: hyperv.h:81
struct quiescer hv_quiescer __quiescer
Hyper-V quiescer.
Definition: hyperv.c:744
#define HV_X64_MSR_EOM
SynIC end of message MSR.
Definition: hyperv.h:58
static struct root_driver hv_root_driver
Hyper-V root device driver.
Definition: hyperv.c:644
static void hv_unmap_synic_no_scontrol(struct hv_hypervisor *hv)
Unmap synthetic interrupt controller, leaving SCONTROL untouched.
Definition: hyperv.c:356
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned int uint32_t
Definition: stdint.h:12
int(* probe)(struct root_device *rootdev)
Add root device.
Definition: device.h:116
#define HV_X64_MSR_HYPERCALL
Hypercall page MSR.
Definition: hyperv.h:43
uint16_t build
Product build number.
Definition: ntlm.h:16
u32 version
Driver version.
Definition: ath9k_hw.c:1983
union hv_message_buffer * message
Message buffer.
Definition: hyperv.h:209
#define EHV(status)
Convert a Hyper-V status code to an iPXE status code.
Definition: hyperv.c:68
static void hv_udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: hyperv.c:795
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
A Hyper-V hypervisor.
Definition: hyperv.h:203
static void * rootdev_get_drvdata(struct root_device *rootdev)
Get root device driver-private data.
Definition: device.h:151
uint32_t len
Length.
Definition: ena.h:14
uint32_t type
Operating system type.
Definition: ena.h:12
#define DBGC2(...)
Definition: compiler.h:522
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
Definition: hyperv.c:423
__builtin_va_list va_list
Definition: stdarg.h:6
#define HV_GUEST_OS_ID_UEFI
Guest OS identity for Gen 2 UEFI firmware.
Definition: hyperv.h:45
const char * name
Name.
Definition: timer.h:30
#define HV_SIEFP_ENABLE
Enable SynIC event flags.
Definition: hyperv.h:54
static int hv_check_features(struct hv_hypervisor *hv)
Check required features.
Definition: hyperv.c:190
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static int hv_check_uefi(struct hv_hypervisor *hv)
Check that Gen 2 UEFI firmware is not running.
Definition: hyperv.c:233
#define HV_SINT_AUTO_EOI
Perform implicit EOI upon synthetic interrupt delivery.
Definition: hyperv.h:60
#define HV_CPUID_HYPERVISOR_ID
Get hypervisor identification.
Definition: hyperv.h:19
Device model.
static void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Definition: malloc.h:77
#define HV_SINT_MASKED
Mask synthetic interrupt.
Definition: hyperv.h:63
struct hv_post_message posted
Posted message.
Definition: hyperv.h:195
#define HV_SIMP_ENABLE
Enable SynIC messages.
Definition: hyperv.h:57
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
Definition: hyperv.c:397
int vmbus_probe(struct hv_hypervisor *hv, struct device *parent)
Probe Hyper-V virtual machine bus.
Definition: vmbus.c:1365
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:45
static void hv_map_synic(struct hv_hypervisor *hv)
Map synthetic interrupt controller.
Definition: hyperv.c:321
#define va_start(ap, last)
Definition: stdarg.h:7
static int hv_check_hv(void)
Check whether or not we are running in Hyper-V.
Definition: hyperv.c:158
#define HV_CPUID_INTERFACE_ID
Get interface identification.
Definition: hyperv.h:16
#define HV_SINT_VECTOR_MASK
Synthetic interrupt vector mask.
Definition: hyperv.h:69
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define HV_MESSAGE_MAX_WAIT_MS
Maximum time to wait for a message response.
Definition: hyperv.c:54
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
String functions.
#define HV_SCONTROL_ENABLE
Enable SynIC.
Definition: hyperv.h:51
#define HV_GUEST_OS_ID_IPXE
Guest OS identity for iPXE.
Definition: hyperv.h:38
Model-specific registers.
uint16_t flag
Flag number.
Definition: hyperv.h:14
static void hv_remove(struct root_device *rootdev)
Remove root device.
Definition: hyperv.c:630
#define HV_SINT_VECTOR(x)
Synthetic interrupt vector.
Definition: hyperv.h:66
struct root_device hv_root_device __root_device
Hyper-V root device.
Definition: hyperv.c:650
struct hv_synic synic
Synthetic interrupt controller (SynIC)
Definition: hyperv.h:207
void * memset(void *dest, int character, size_t len) __nonnull
static void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: settings_ui.c:285