mirror of https://github.com/ipxe/ipxe.git
243 lines
5.9 KiB
C
243 lines
5.9 KiB
C
#ifndef _IPXE_HYPERV_H
|
|
#define _IPXE_HYPERV_H
|
|
|
|
/** @file
|
|
*
|
|
* Hyper-V interface
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|
|
|
#include <stdint.h>
|
|
#include <ipxe/io.h>
|
|
|
|
/** Hyper-V interface identification */
|
|
#define HV_INTERFACE_ID 0x31237648 /* "Hv#1" */
|
|
|
|
/** Guest OS identity for iPXE
|
|
*
|
|
* This field comprises:
|
|
*
|
|
* Bit 63 : set to 1 to indicate an open source OS
|
|
* Bits 62:56 : OS Type
|
|
* Bits 55:48 : OS ID
|
|
* Bits 47:16 : Version
|
|
* Bits 15:0 : Build number
|
|
*
|
|
* There appears to be no central registry for the "OS Type". The
|
|
* specification states that "Linux is 0x100", and the FreeBSD source
|
|
* states that "FreeBSD is 0x200". Both of these statements are
|
|
* actually referring to the combined "OS Type" and "OS ID" field.
|
|
*
|
|
* We choose to use 0x98ae: this is generated by setting bit 63 (to
|
|
* indicate an open source OS) and setting the OS Type+ID equal to the
|
|
* PnP vendor ID used in romprefix.S. No version information or build
|
|
* number is included.
|
|
*/
|
|
#define HV_GUEST_OS_ID_IPXE ( ( 1ULL << 63 ) | ( 0x18aeULL << 48 ) )
|
|
|
|
/** Guest OS identity for Gen 2 UEFI firmware
|
|
*
|
|
* This does not conform to the documented structure for guest OS
|
|
* identities.
|
|
*/
|
|
#define HV_GUEST_OS_ID_UEFI ( 1ULL << 40 )
|
|
|
|
/** Enable hypercall page */
|
|
#define HV_HYPERCALL_ENABLE 0x00000001UL
|
|
|
|
/** Enable SynIC */
|
|
#define HV_SCONTROL_ENABLE 0x00000001UL
|
|
|
|
/** Enable SynIC event flags */
|
|
#define HV_SIEFP_ENABLE 0x00000001UL
|
|
|
|
/** Enable SynIC messages */
|
|
#define HV_SIMP_ENABLE 0x00000001UL
|
|
|
|
/** Perform implicit EOI upon synthetic interrupt delivery */
|
|
#define HV_SINT_AUTO_EOI 0x00020000UL
|
|
|
|
/** Mask synthetic interrupt */
|
|
#define HV_SINT_MASKED 0x00010000UL
|
|
|
|
/** Synthetic interrupt vector */
|
|
#define HV_SINT_VECTOR(x) ( (x) << 0 )
|
|
|
|
/** Synthetic interrupt vector mask */
|
|
#define HV_SINT_VECTOR_MASK HV_SINT_VECTOR ( 0xff )
|
|
|
|
/** Maximum synthetic interrupt number */
|
|
#define HV_SINT_MAX 15
|
|
|
|
/** Post message */
|
|
#define HV_POST_MESSAGE 0x005c
|
|
|
|
/** A posted message
|
|
*
|
|
* This is the input parameter list for the HvPostMessage hypercall.
|
|
*/
|
|
struct hv_post_message {
|
|
/** Connection ID */
|
|
uint32_t id;
|
|
/** Padding */
|
|
uint32_t reserved;
|
|
/** Type */
|
|
uint32_t type;
|
|
/** Length of message */
|
|
uint32_t len;
|
|
/** Message */
|
|
uint8_t data[240];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A received message
|
|
*
|
|
* This is the HV_MESSAGE structure from the Hypervisor Top-Level
|
|
* Functional Specification. The field order given in the
|
|
* documentation is incorrect.
|
|
*/
|
|
struct hv_message {
|
|
/** Type */
|
|
uint32_t type;
|
|
/** Length of message */
|
|
uint8_t len;
|
|
/** Flags */
|
|
uint8_t flags;
|
|
/** Padding */
|
|
uint16_t reserved;
|
|
/** Origin */
|
|
uint64_t origin;
|
|
/** Message */
|
|
uint8_t data[240];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Signal event */
|
|
#define HV_SIGNAL_EVENT 0x005d
|
|
|
|
/** A signalled event */
|
|
struct hv_signal_event {
|
|
/** Connection ID */
|
|
uint32_t id;
|
|
/** Flag number */
|
|
uint16_t flag;
|
|
/** Reserved */
|
|
uint16_t reserved;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A received event */
|
|
struct hv_event {
|
|
/** Event flags */
|
|
uint8_t flags[256];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A monitor trigger group
|
|
*
|
|
* This is the HV_MONITOR_TRIGGER_GROUP structure from the Hypervisor
|
|
* Top-Level Functional Specification.
|
|
*/
|
|
struct hv_monitor_trigger {
|
|
/** Pending events */
|
|
uint32_t pending;
|
|
/** Armed events */
|
|
uint32_t armed;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A monitor parameter set
|
|
*
|
|
* This is the HV_MONITOR_PARAMETER structure from the Hypervisor
|
|
* Top-Level Functional Specification.
|
|
*/
|
|
struct hv_monitor_parameter {
|
|
/** Connection ID */
|
|
uint32_t id;
|
|
/** Flag number */
|
|
uint16_t flag;
|
|
/** Reserved */
|
|
uint16_t reserved;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A monitor page
|
|
*
|
|
* This is the HV_MONITOR_PAGE structure from the Hypervisor Top-Level
|
|
* Functional Specification.
|
|
*/
|
|
struct hv_monitor {
|
|
/** Flags */
|
|
uint32_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved_a[4];
|
|
/** Trigger groups */
|
|
struct hv_monitor_trigger trigger[4];
|
|
/** Reserved */
|
|
uint8_t reserved_b[536];
|
|
/** Latencies */
|
|
uint16 latency[4][32];
|
|
/** Reserved */
|
|
uint8_t reserved_c[256];
|
|
/** Parameters */
|
|
struct hv_monitor_parameter param[4][32];
|
|
/** Reserved */
|
|
uint8_t reserved_d[1984];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A synthetic interrupt controller */
|
|
struct hv_synic {
|
|
/** Message page */
|
|
struct hv_message *message;
|
|
/** Event flag page */
|
|
struct hv_event *event;
|
|
};
|
|
|
|
/** A message buffer */
|
|
union hv_message_buffer {
|
|
/** Posted message */
|
|
struct hv_post_message posted;
|
|
/** Received message */
|
|
struct hv_message received;
|
|
/** Signalled event */
|
|
struct hv_signal_event signalled;
|
|
};
|
|
|
|
/** A Hyper-V hypervisor */
|
|
struct hv_hypervisor {
|
|
/** Hypercall page */
|
|
void *hypercall;
|
|
/** Synthetic interrupt controller (SynIC) */
|
|
struct hv_synic synic;
|
|
/** Message buffer */
|
|
union hv_message_buffer *message;
|
|
/** Virtual machine bus */
|
|
struct vmbus *vmbus;
|
|
};
|
|
|
|
#include <bits/hyperv.h>
|
|
|
|
/**
|
|
* Calculate the number of pages covering an address range
|
|
*
|
|
* @v data Start of data
|
|
* @v len Length of data (must be non-zero)
|
|
* @ret pfn_count Number of pages covered
|
|
*/
|
|
static inline unsigned int hv_pfn_count ( physaddr_t data, size_t len ) {
|
|
unsigned int first_pfn = ( data / PAGE_SIZE );
|
|
unsigned int last_pfn = ( ( data + len - 1 ) / PAGE_SIZE );
|
|
|
|
return ( last_pfn - first_pfn + 1 );
|
|
}
|
|
|
|
extern __attribute__ (( sentinel )) int
|
|
hv_alloc_pages ( struct hv_hypervisor *hv, ... );
|
|
extern __attribute__ (( sentinel )) void
|
|
hv_free_pages ( struct hv_hypervisor *hv, ... );
|
|
extern void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx );
|
|
extern void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx );
|
|
extern int hv_post_message ( struct hv_hypervisor *hv, unsigned int id,
|
|
unsigned int type, const void *data, size_t len );
|
|
extern int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx );
|
|
extern int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id,
|
|
unsigned int flag );
|
|
|
|
#endif /* _IPXE_HYPERV_H */
|