These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / x86 / drivers / hyperv / hyperv.c
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/cpuid.h>
43 #include <ipxe/msr.h>
44 #include <ipxe/hyperv.h>
45 #include <ipxe/vmbus.h>
46 #include "hyperv.h"
47
48 /** Maximum time to wait for a message response
49  *
50  * This is a policy decision.
51  */
52 #define HV_MESSAGE_MAX_WAIT_MS 1000
53
54 /**
55  * Convert a Hyper-V status code to an iPXE status code
56  *
57  * @v status            Hyper-V status code
58  * @ret rc              iPXE status code (before negation)
59  */
60 #define EHV( status ) EPLATFORM ( EINFO_EPLATFORM, (status) )
61
62 /**
63  * Allocate zeroed pages
64  *
65  * @v hv                Hyper-V hypervisor
66  * @v ...               Page addresses to fill in, terminated by NULL
67  * @ret rc              Return status code
68  */
69 __attribute__ (( sentinel )) int
70 hv_alloc_pages ( struct hv_hypervisor *hv, ... ) {
71         va_list args;
72         void **page;
73         int i;
74
75         /* Allocate and zero pages */
76         va_start ( args, hv );
77         for ( i = 0 ; ( ( page = va_arg ( args, void ** ) ) != NULL ); i++ ) {
78                 *page = malloc_dma ( PAGE_SIZE, PAGE_SIZE );
79                 if ( ! *page )
80                         goto err_alloc;
81                 memset ( *page, 0, PAGE_SIZE );
82         }
83         va_end ( args );
84
85         return 0;
86
87  err_alloc:
88         va_end ( args );
89         va_start ( args, hv );
90         for ( ; i >= 0 ; i-- ) {
91                 page = va_arg ( args, void ** );
92                 free_dma ( *page, PAGE_SIZE );
93         }
94         va_end ( args );
95         return -ENOMEM;
96 }
97
98 /**
99  * Free pages
100  *
101  * @v hv                Hyper-V hypervisor
102  * @v ...               Page addresses, terminated by NULL
103  */
104 __attribute__ (( sentinel )) void
105 hv_free_pages ( struct hv_hypervisor *hv, ... ) {
106         va_list args;
107         void *page;
108
109         va_start ( args, hv );
110         while ( ( page = va_arg ( args, void * ) ) != NULL )
111                 free_dma ( page, PAGE_SIZE );
112         va_end ( args );
113 }
114
115 /**
116  * Allocate message buffer
117  *
118  * @v hv                Hyper-V hypervisor
119  * @ret rc              Return status code
120  */
121 static int hv_alloc_message ( struct hv_hypervisor *hv ) {
122
123         /* Allocate buffer.  Must be aligned to at least 8 bytes and
124          * must not cross a page boundary, so align on its own size.
125          */
126         hv->message = malloc_dma ( sizeof ( *hv->message ),
127                                    sizeof ( *hv->message ) );
128         if ( ! hv->message )
129                 return -ENOMEM;
130
131         return 0;
132 }
133
134 /**
135  * Free message buffer
136  *
137  * @v hv                Hyper-V hypervisor
138  */
139 static void hv_free_message ( struct hv_hypervisor *hv ) {
140
141         /* Free buffer */
142         free_dma ( hv->message, sizeof ( *hv->message ) );
143 }
144
145 /**
146  * Check whether or not we are running in Hyper-V
147  *
148  * @v hv                Hyper-V hypervisor
149  * @ret rc              Return status code
150  */
151 static int hv_check_hv ( struct hv_hypervisor *hv ) {
152         struct x86_features features;
153         uint32_t interface_id;
154         uint32_t discard_ebx;
155         uint32_t discard_ecx;
156         uint32_t discard_edx;
157         uint32_t available;
158         uint32_t permissions;
159
160         /* Check for presence of a hypervisor (not necessarily Hyper-V) */
161         x86_features ( &features );
162         if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_HYPERVISOR ) ) {
163                 DBGC ( hv, "HV %p not running in a hypervisor\n", hv );
164                 return -ENODEV;
165         }
166
167         /* Check that hypervisor is Hyper-V */
168         cpuid ( HV_CPUID_INTERFACE_ID, &interface_id, &discard_ebx,
169                 &discard_ecx, &discard_edx );
170         if ( interface_id != HV_INTERFACE_ID ) {
171                 DBGC ( hv, "HV %p not running in Hyper-V (interface ID "
172                        "%#08x)\n", hv, interface_id );
173                 return -ENODEV;
174         }
175
176         /* Check that required features and privileges are available */
177         cpuid ( HV_CPUID_FEATURES, &available, &permissions, &discard_ecx,
178                 &discard_edx );
179         if ( ! ( available & HV_FEATURES_AVAIL_HYPERCALL_MSR ) ) {
180                 DBGC ( hv, "HV %p has no hypercall MSRs (features %08x:%08x)\n",
181                        hv, available, permissions );
182                 return -ENODEV;
183         }
184         if ( ! ( available & HV_FEATURES_AVAIL_SYNIC_MSR ) ) {
185                 DBGC ( hv, "HV %p has no SynIC MSRs (features %08x:%08x)\n",
186                        hv, available, permissions );
187                 return -ENODEV;
188         }
189         if ( ! ( permissions & HV_FEATURES_PERM_POST_MESSAGES ) ) {
190                 DBGC ( hv, "HV %p cannot post messages (features %08x:%08x)\n",
191                        hv, available, permissions );
192                 return -EACCES;
193         }
194         if ( ! ( permissions & HV_FEATURES_PERM_SIGNAL_EVENTS ) ) {
195                 DBGC ( hv, "HV %p cannot signal events (features %08x:%08x)",
196                        hv, available, permissions );
197                 return -EACCES;
198         }
199
200         return 0;
201 }
202
203 /**
204  * Map hypercall page
205  *
206  * @v hv                Hyper-V hypervisor
207  * @ret rc              Return status code
208  */
209 static int hv_map_hypercall ( struct hv_hypervisor *hv ) {
210         union {
211                 struct {
212                         uint32_t ebx;
213                         uint32_t ecx;
214                         uint32_t edx;
215                 } __attribute__ (( packed ));
216                 char text[ 13 /* "bbbbccccdddd" + NUL */ ];
217         } vendor_id;
218         uint32_t build;
219         uint32_t version;
220         uint32_t discard_eax;
221         uint32_t discard_ecx;
222         uint32_t discard_edx;
223         uint64_t guest_os_id;
224         uint64_t hypercall;
225
226         /* Report guest OS identity */
227         guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID );
228         if ( guest_os_id != 0 ) {
229                 DBGC ( hv, "HV %p guest OS ID MSR already set to %#08llx\n",
230                        hv, guest_os_id );
231                 return -EBUSY;
232         }
233         guest_os_id = HV_GUEST_OS_ID_IPXE;
234         DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
235         wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id );
236
237         /* Get hypervisor system identity (for debugging) */
238         cpuid ( HV_CPUID_VENDOR_ID, &discard_eax, &vendor_id.ebx,
239                 &vendor_id.ecx, &vendor_id.edx );
240         vendor_id.text[ sizeof ( vendor_id.text ) - 1 ] = '\0';
241         cpuid ( HV_CPUID_HYPERVISOR_ID, &build, &version, &discard_ecx,
242                 &discard_edx );
243         DBGC ( hv, "HV %p detected \"%s\" version %d.%d build %d\n", hv,
244                vendor_id.text, ( version >> 16 ), ( version & 0xffff ), build );
245
246         /* Map hypercall page */
247         hypercall = rdmsr ( HV_X64_MSR_HYPERCALL );
248         hypercall &= ( PAGE_SIZE - 1 );
249         hypercall |= ( virt_to_phys ( hv->hypercall ) | HV_HYPERCALL_ENABLE );
250         DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall );
251         wrmsr ( HV_X64_MSR_HYPERCALL, hypercall );
252
253         return 0;
254 }
255
256 /**
257  * Unmap hypercall page
258  *
259  * @v hv                Hyper-V hypervisor
260  */
261 static void hv_unmap_hypercall ( struct hv_hypervisor *hv ) {
262         uint64_t hypercall;
263         uint64_t guest_os_id;
264
265         /* Unmap the hypercall page */
266         hypercall = rdmsr ( HV_X64_MSR_HYPERCALL );
267         hypercall &= ( ( PAGE_SIZE - 1 ) & ~HV_HYPERCALL_ENABLE );
268         DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall );
269         wrmsr ( HV_X64_MSR_HYPERCALL, hypercall );
270
271         /* Reset the guest OS identity */
272         guest_os_id = 0;
273         DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
274         wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id );
275 }
276
277 /**
278  * Map synthetic interrupt controller
279  *
280  * @v hv                Hyper-V hypervisor
281  * @ret rc              Return status code
282  */
283 static int hv_map_synic ( struct hv_hypervisor *hv ) {
284         uint64_t simp;
285         uint64_t siefp;
286         uint64_t scontrol;
287
288         /* Map SynIC message page */
289         simp = rdmsr ( HV_X64_MSR_SIMP );
290         simp &= ( PAGE_SIZE - 1 );
291         simp |= ( virt_to_phys ( hv->synic.message ) | HV_SIMP_ENABLE );
292         DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp );
293         wrmsr ( HV_X64_MSR_SIMP, simp );
294
295         /* Map SynIC event page */
296         siefp = rdmsr ( HV_X64_MSR_SIEFP );
297         siefp &= ( PAGE_SIZE - 1 );
298         siefp |= ( virt_to_phys ( hv->synic.event ) | HV_SIEFP_ENABLE );
299         DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp );
300         wrmsr ( HV_X64_MSR_SIEFP, siefp );
301
302         /* Enable SynIC */
303         scontrol = rdmsr ( HV_X64_MSR_SCONTROL );
304         scontrol |= HV_SCONTROL_ENABLE;
305         DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
306         wrmsr ( HV_X64_MSR_SCONTROL, scontrol );
307
308         return 0;
309 }
310
311 /**
312  * Unmap synthetic interrupt controller
313  *
314  * @v hv                Hyper-V hypervisor
315  */
316 static void hv_unmap_synic ( struct hv_hypervisor *hv ) {
317         uint64_t scontrol;
318         uint64_t siefp;
319         uint64_t simp;
320
321         /* Disable SynIC */
322         scontrol = rdmsr ( HV_X64_MSR_SCONTROL );
323         scontrol &= ~HV_SCONTROL_ENABLE;
324         DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
325         wrmsr ( HV_X64_MSR_SCONTROL, scontrol );
326
327         /* Unmap SynIC event page */
328         siefp = rdmsr ( HV_X64_MSR_SIEFP );
329         siefp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIEFP_ENABLE );
330         DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp );
331         wrmsr ( HV_X64_MSR_SIEFP, siefp );
332
333         /* Unmap SynIC message page */
334         simp = rdmsr ( HV_X64_MSR_SIMP );
335         simp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIMP_ENABLE );
336         DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp );
337         wrmsr ( HV_X64_MSR_SIMP, simp );
338 }
339
340 /**
341  * Enable synthetic interrupt
342  *
343  * @v hv                Hyper-V hypervisor
344  * @v sintx             Synthetic interrupt number
345  */
346 void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) {
347         unsigned long msr = HV_X64_MSR_SINT ( sintx );
348         uint64_t sint;
349
350         /* Enable synthetic interrupt
351          *
352          * We have to enable the interrupt, otherwise messages will
353          * not be delivered (even though the documentation implies
354          * that polling for messages is possible).  We enable AutoEOI
355          * and hook the interrupt to the obsolete IRQ13 (FPU
356          * exception) vector, which will be implemented as a no-op.
357          */
358         sint = rdmsr ( msr );
359         sint &= ~( HV_SINT_MASKED | HV_SINT_VECTOR_MASK );
360         sint |= ( HV_SINT_AUTO_EOI |
361                   HV_SINT_VECTOR ( IRQ_INT ( 13 /* See comment above */ ) ) );
362         DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
363         wrmsr ( msr, sint );
364 }
365
366 /**
367  * Disable synthetic interrupt
368  *
369  * @v hv                Hyper-V hypervisor
370  * @v sintx             Synthetic interrupt number
371  */
372 void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) {
373         unsigned long msr = HV_X64_MSR_SINT ( sintx );
374         uint64_t sint;
375
376         /* Disable synthetic interrupt */
377         sint = rdmsr ( msr );
378         sint &= ~HV_SINT_AUTO_EOI;
379         sint |= HV_SINT_MASKED;
380         DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
381         wrmsr ( msr, sint );
382 }
383
384 /**
385  * Post message
386  *
387  * @v hv                Hyper-V hypervisor
388  * @v id                Connection ID
389  * @v type              Message type
390  * @v data              Message
391  * @v len               Length of message
392  * @ret rc              Return status code
393  */
394 int hv_post_message ( struct hv_hypervisor *hv, unsigned int id,
395                       unsigned int type, const void *data, size_t len ) {
396         struct hv_post_message *msg = &hv->message->posted;
397         int status;
398         int rc;
399
400         /* Sanity check */
401         assert ( len <= sizeof ( msg->data ) );
402
403         /* Construct message */
404         memset ( msg, 0, sizeof ( *msg ) );
405         msg->id = cpu_to_le32 ( id );
406         msg->type = cpu_to_le32 ( type );
407         msg->len = cpu_to_le32 ( len );
408         memcpy ( msg->data, data, len );
409         DBGC2 ( hv, "HV %p connection %d posting message type %#08x:\n",
410                 hv, id, type );
411         DBGC2_HDA ( hv, 0, msg->data, len );
412
413         /* Post message */
414         if ( ( status = hv_call ( hv, HV_POST_MESSAGE, msg, NULL ) ) != 0 ) {
415                 rc = -EHV ( status );
416                 DBGC ( hv, "HV %p could not post message to %#08x: %s\n",
417                        hv, id, strerror ( rc ) );
418                 return rc;
419         }
420
421         return 0;
422 }
423
424 /**
425  * Wait for received message
426  *
427  * @v hv                Hyper-V hypervisor
428  * @v sintx             Synthetic interrupt number
429  * @ret rc              Return status code
430  */
431 int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx ) {
432         struct hv_message *msg = &hv->message->received;
433         struct hv_message *src = &hv->synic.message[sintx];
434         unsigned int retries;
435         size_t len;
436
437         /* Wait for message to arrive */
438         for ( retries = 0 ; retries < HV_MESSAGE_MAX_WAIT_MS ; retries++ ) {
439
440                 /* Check for message */
441                 if ( src->type ) {
442
443                         /* Copy message */
444                         memset ( msg, 0, sizeof ( *msg ) );
445                         len = src->len;
446                         assert ( len <= sizeof ( *msg ) );
447                         memcpy ( msg, src,
448                                  ( offsetof ( typeof ( *msg ), data ) + len ) );
449                         DBGC2 ( hv, "HV %p SINT%d received message type "
450                                 "%#08x:\n", hv, sintx,
451                                 le32_to_cpu ( msg->type ) );
452                         DBGC2_HDA ( hv, 0, msg->data, len );
453
454                         /* Consume message */
455                         src->type = 0;
456
457                         return 0;
458                 }
459
460                 /* Trigger message delivery */
461                 wrmsr ( HV_X64_MSR_EOM, 0 );
462
463                 /* Delay */
464                 mdelay ( 1 );
465         }
466
467         DBGC ( hv, "HV %p SINT%d timed out waiting for message\n",
468                hv, sintx );
469         return -ETIMEDOUT;
470 }
471
472 /**
473  * Signal event
474  *
475  * @v hv                Hyper-V hypervisor
476  * @v id                Connection ID
477  * @v flag              Flag number
478  * @ret rc              Return status code
479  */
480 int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id,
481                       unsigned int flag ) {
482         struct hv_signal_event *event = &hv->message->signalled;
483         int status;
484         int rc;
485
486         /* Construct event */
487         memset ( event, 0, sizeof ( *event ) );
488         event->id = cpu_to_le32 ( id );
489         event->flag = cpu_to_le16 ( flag );
490
491         /* Signal event */
492         if ( ( status = hv_call ( hv, HV_SIGNAL_EVENT, event, NULL ) ) != 0 ) {
493                 rc = -EHV ( status );
494                 DBGC ( hv, "HV %p could not signal event to %#08x: %s\n",
495                        hv, id, strerror ( rc ) );
496                 return rc;
497         }
498
499         return 0;
500 }
501
502 /**
503  * Probe root device
504  *
505  * @v rootdev           Root device
506  * @ret rc              Return status code
507  */
508 static int hv_probe ( struct root_device *rootdev ) {
509         struct hv_hypervisor *hv;
510         int rc;
511
512         /* Allocate and initialise structure */
513         hv = zalloc ( sizeof ( *hv ) );
514         if ( ! hv ) {
515                 rc = -ENOMEM;
516                 goto err_alloc;
517         }
518
519         /* Check we are running in Hyper-V */
520         if ( ( rc = hv_check_hv ( hv ) ) != 0 )
521                 goto err_check_hv;
522
523         /* Allocate pages */
524         if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message,
525                                      &hv->synic.event, NULL ) ) != 0 )
526                 goto err_alloc_pages;
527
528         /* Allocate message buffer */
529         if ( ( rc = hv_alloc_message ( hv ) ) != 0 )
530                 goto err_alloc_message;
531
532         /* Map hypercall page */
533         if ( ( rc = hv_map_hypercall ( hv ) ) != 0 )
534                 goto err_map_hypercall;
535
536         /* Map synthetic interrupt controller */
537         if ( ( rc = hv_map_synic ( hv ) ) != 0 )
538                 goto err_map_synic;
539
540         /* Probe Hyper-V devices */
541         if ( ( rc = vmbus_probe ( hv, &rootdev->dev ) ) != 0 )
542                 goto err_vmbus_probe;
543
544         rootdev_set_drvdata ( rootdev, hv );
545         return 0;
546
547         vmbus_remove ( hv, &rootdev->dev );
548  err_vmbus_probe:
549         hv_unmap_synic ( hv );
550  err_map_synic:
551         hv_unmap_hypercall ( hv );
552  err_map_hypercall:
553         hv_free_message ( hv );
554  err_alloc_message:
555         hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
556                         NULL );
557  err_alloc_pages:
558  err_check_hv:
559         free ( hv );
560  err_alloc:
561         return rc;
562 }
563
564 /**
565  * Remove root device
566  *
567  * @v rootdev           Root device
568  */
569 static void hv_remove ( struct root_device *rootdev ) {
570         struct hv_hypervisor *hv = rootdev_get_drvdata ( rootdev );
571
572         vmbus_remove ( hv, &rootdev->dev );
573         hv_unmap_synic ( hv );
574         hv_unmap_hypercall ( hv );
575         hv_free_message ( hv );
576         hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
577                         NULL );
578         free ( hv );
579 }
580
581 /** Hyper-V root device driver */
582 static struct root_driver hv_root_driver = {
583         .probe = hv_probe,
584         .remove = hv_remove,
585 };
586
587 /** Hyper-V root device */
588 struct root_device hv_root_device __root_device = {
589         .dev = { .name = "Hyper-V" },
590         .driver = &hv_root_driver,
591 };
592
593 /* Drag in objects via hv_root_device */
594 REQUIRING_SYMBOL ( hv_root_device );
595
596 /* Drag in netvsc driver */
597 REQUIRE_OBJECT ( netvsc );