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