These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / x86_64 / include / bits / hyperv.h
1 #ifndef _BITS_HYPERV_H
2 #define _BITS_HYPERV_H
3
4 /** @file
5  *
6  * Hyper-V interface
7  *
8  */
9
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <ipxe/io.h>
15
16 /**
17  * Issue hypercall
18  *
19  * @v hv                Hyper-V hypervisor
20  * @v code              Call code
21  * @v in                Input parameters
22  * @v out               Output parameters
23  * @ret status          Status code
24  */
25 static inline __attribute__ (( always_inline )) int
26 hv_call ( struct hv_hypervisor *hv, unsigned int code, const void *in,
27           void *out ) {
28         void *hypercall = hv->hypercall;
29         register uint64_t rcx asm ( "rcx" );
30         register uint64_t rdx asm ( "rdx" );
31         register uint64_t r8 asm ( "r8" );
32         uint64_t in_phys;
33         uint64_t out_phys;
34         uint16_t result;
35
36         in_phys = ( ( __builtin_constant_p ( in ) && ( in == NULL ) )
37                        ? 0 : virt_to_phys ( in ) );
38         out_phys = ( ( __builtin_constant_p ( out ) && ( out == NULL ) )
39                        ? 0 : virt_to_phys ( out ) );
40         rcx = code;
41         rdx = in_phys;
42         r8 = out_phys;
43         __asm__ __volatile__ ( "call *%4"
44                                : "=a" ( result ), "+r" ( rcx ), "+r" ( rdx ),
45                                  "+r" ( r8 )
46                                : "m" ( hypercall )
47                                : "r9", "r10", "r11", "xmm0", "xmm1", "xmm2",
48                                  "xmm3", "xmm4", "xmm5" );
49         return result;
50 }
51
52 /**
53  * Set bit atomically
54  *
55  * @v bits              Bit field
56  * @v bit               Bit to set
57  */
58 static inline __attribute__ (( always_inline )) void
59 hv_set_bit ( void *bits, unsigned int bit ) {
60         struct {
61                 uint64_t qword[ ( bit / 64 ) + 1 ];
62         } *qwords = bits;
63
64         /* Set bit using "lock bts".  Inform compiler that any memory
65          * from the start of the bit field up to and including the
66          * qword containing this bit may be modified.  (This is
67          * overkill but shouldn't matter in practice since we're
68          * unlikely to subsequently read other bits from the same bit
69          * field.)
70          */
71         __asm__ __volatile__ ( "lock bts %1, %0"
72                                : "+m" ( *qwords ) : "Ir" ( bit ) );
73 }
74
75 #endif /* _BITS_HYPERV_H */