diff options
| author | Michael Brown | 2014-12-11 18:22:18 +0100 |
|---|---|---|
| committer | Michael Brown | 2014-12-18 17:27:27 +0100 |
| commit | d77a546fb4c69546a81440bdeb0553b8db1d3de8 (patch) | |
| tree | 8fa8d90c636e3f1302981a4e09804deb0024c5b4 /src/arch/x86_64 | |
| parent | [rndis] Add generic RNDIS device abstraction (diff) | |
| download | ipxe-d77a546fb4c69546a81440bdeb0553b8db1d3de8.tar.gz ipxe-d77a546fb4c69546a81440bdeb0553b8db1d3de8.tar.xz ipxe-d77a546fb4c69546a81440bdeb0553b8db1d3de8.zip | |
[hyperv] Add support for Hyper-V hypervisor
Add support for detecting and communicating with the Hyper-V
hypervisor.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/x86_64')
| -rw-r--r-- | src/arch/x86_64/include/bits/hyperv.h | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/arch/x86_64/include/bits/hyperv.h b/src/arch/x86_64/include/bits/hyperv.h new file mode 100644 index 000000000..88a3d559b --- /dev/null +++ b/src/arch/x86_64/include/bits/hyperv.h @@ -0,0 +1,75 @@ +#ifndef _BITS_HYPERV_H +#define _BITS_HYPERV_H + +/** @file + * + * Hyper-V interface + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#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 */ |
