diff options
author | Michael Brown <mcb30@ipxe.org> | 2014-07-28 23:38:30 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2014-07-29 15:57:44 +0100 |
commit | 036af27a4523c4e15e28d30a1513a3f6d9671774 (patch) | |
tree | bf284637f91e2258906d736f07a54b1f98dfd68d /src/include | |
parent | ec94a8798f8fbba42628946108d6d9607a980da4 (diff) | |
download | ipxe-036af27a4523c4e15e28d30a1513a3f6d9671774.tar.gz |
[xen] Add basic support for PV-HVM domains
Add basic support for Xen PV-HVM domains (detected via the Xen
platform PCI device with IDs 5853:0001), including support for
accessing configuration via XenStore and enumerating devices via
XenBus.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/ipxe/device.h | 3 | ||||
-rw-r--r-- | src/include/ipxe/errfile.h | 3 | ||||
-rw-r--r-- | src/include/ipxe/xen.h | 73 | ||||
-rw-r--r-- | src/include/ipxe/xenbus.h | 85 | ||||
-rw-r--r-- | src/include/ipxe/xenevent.h | 59 | ||||
-rw-r--r-- | src/include/ipxe/xengrant.h | 102 | ||||
-rw-r--r-- | src/include/ipxe/xenmem.h | 46 | ||||
-rw-r--r-- | src/include/ipxe/xenstore.h | 29 | ||||
-rw-r--r-- | src/include/ipxe/xenver.h | 44 |
9 files changed, 444 insertions, 0 deletions
diff --git a/src/include/ipxe/device.h b/src/include/ipxe/device.h index 895097349..7202a6966 100644 --- a/src/include/ipxe/device.h +++ b/src/include/ipxe/device.h @@ -60,6 +60,9 @@ struct device_description { /** EFI bus type */ #define BUS_TYPE_EFI 7 +/** Xen bus type */ +#define BUS_TYPE_XEN 8 + /** A hardware device */ struct device { /** Name */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index a8b3a8e4a..3fa499ddb 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -301,6 +301,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_memmap_settings ( ERRFILE_OTHER | 0x003f0000 ) #define ERRFILE_param_cmd ( ERRFILE_OTHER | 0x00400000 ) #define ERRFILE_deflate ( ERRFILE_OTHER | 0x00410000 ) +#define ERRFILE_xenstore ( ERRFILE_OTHER | 0x00420000 ) +#define ERRFILE_xenbus ( ERRFILE_OTHER | 0x00430000 ) +#define ERRFILE_xengrant ( ERRFILE_OTHER | 0x00440000 ) /** @} */ diff --git a/src/include/ipxe/xen.h b/src/include/ipxe/xen.h new file mode 100644 index 000000000..546b0c348 --- /dev/null +++ b/src/include/ipxe/xen.h @@ -0,0 +1,73 @@ +#ifndef _IPXE_XEN_H +#define _IPXE_XEN_H + +/** @file + * + * Xen interface + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/* Define Xen interface version before including any Xen header files */ +#define __XEN_INTERFACE_VERSION__ 0x00040400 + +#include <stdint.h> +#include <ipxe/uaccess.h> +#include <xen/xen.h> +#include <xen/event_channel.h> + +/* Memory barrier macros used by ring.h */ +#define xen_mb() mb() +#define xen_rmb() rmb() +#define xen_wmb() wmb() + +struct xen_hypercall; + +/** A Xen grant table */ +struct xen_grant { + /** Grant table entries */ + union grant_entry_v2 *table; + /** Number of grant table entries (must be a power of two) */ + unsigned int count; + /** Number of grant table entries in use */ + unsigned int used; + /** Most recently used grant reference */ + unsigned int ref; +}; + +/** A XenStore */ +struct xen_store { + /** XenStore domain interface */ + struct xenstore_domain_interface *intf; + /** Event channel */ + evtchn_port_t port; +}; + +/** A Xen hypervisor */ +struct xen_hypervisor { + /** Hypercall table */ + struct xen_hypercall *hypercall; + /** Shared info page */ + struct shared_info *shared; + /** Grant table */ + struct xen_grant grant; + /** XenStore */ + struct xen_store store; +}; + +#include <bits/xen.h> + +/** + * Convert a Xen status code to an iPXE status code + * + * @v xenrc Xen status code (negated) + * @ret rc iPXE status code (before negation) + * + * Xen status codes are defined in the file include/xen/errno.h in the + * Xen repository. They happen to match the Linux error codes, some + * of which can be found in our include/ipxe/errno/linux.h. + */ +#define EXEN( xenrc ) EPLATFORM ( EINFO_EPLATFORM, -(xenrc) ) + +#endif /* _IPXE_XEN_H */ diff --git a/src/include/ipxe/xenbus.h b/src/include/ipxe/xenbus.h new file mode 100644 index 000000000..2777226fd --- /dev/null +++ b/src/include/ipxe/xenbus.h @@ -0,0 +1,85 @@ +#ifndef _IPXE_XENBUS_H +#define _IPXE_XENBUS_H + +/** @file + * + * Xen device bus + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/device.h> +#include <ipxe/tables.h> +#include <ipxe/xen.h> +#include <xen/io/xenbus.h> + +/** A Xen device */ +struct xen_device { + /** Generic iPXE device */ + struct device dev; + /** Xen hypervisor */ + struct xen_hypervisor *xen; + /** XenStore key */ + char *key; + /** Backend XenStore key */ + char *backend; + /** Backend domain ID */ + unsigned long backend_id; + /** Driver */ + struct xen_driver *driver; + /** Driver-private data */ + void *priv; +}; + +/** A Xen device driver */ +struct xen_driver { + /** Name */ + const char *name; + /** Device type */ + const char *type; + /** Probe device + * + * @v xendev Xen device + * @ret rc Return status code + */ + int ( * probe ) ( struct xen_device *xendev ); + /** Remove device + * + * @v xendev Xen device + */ + void ( * remove ) ( struct xen_device *xendev ); +}; + +/** Xen device driver table */ +#define XEN_DRIVERS __table ( struct xen_driver, "xen_drivers" ) + +/** Declare a Xen device driver */ +#define __xen_driver __table_entry ( XEN_DRIVERS, 01 ) + +/** + * Set Xen device driver-private data + * + * @v xendev Xen device + * @v priv Private data + */ +static inline void xen_set_drvdata ( struct xen_device *xendev, void *priv ) { + xendev->priv = priv; +} + +/** + * Get Xen device driver-private data + * + * @v xendev Xen device + * @ret priv Private data + */ +static inline void * xen_get_drvdata ( struct xen_device *xendev ) { + return xendev->priv; +} + +extern int xenbus_set_state ( struct xen_device *xendev, int state ); +extern int xenbus_backend_wait ( struct xen_device *xendev, int state ); +extern int xenbus_probe ( struct xen_hypervisor *xen, struct device *parent ); +extern void xenbus_remove ( struct xen_hypervisor *xen, struct device *parent ); + +#endif /* _IPXE_XENBUS_H */ diff --git a/src/include/ipxe/xenevent.h b/src/include/ipxe/xenevent.h new file mode 100644 index 000000000..1dd6a0c0b --- /dev/null +++ b/src/include/ipxe/xenevent.h @@ -0,0 +1,59 @@ +#ifndef _IPXE_XENEVENT_H +#define _IPXE_XENEVENT_H + +/** @file + * + * Xen events + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/xen.h> +#include <xen/event_channel.h> + +/** + * Close event channel + * + * @v xen Xen hypervisor + * @v close Event descriptor + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xenevent_close ( struct xen_hypervisor *xen, struct evtchn_close *close ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_event_channel_op, + EVTCHNOP_close, virt_to_phys ( close ) ); +} + +/** + * Send event + * + * @v xen Xen hypervisor + * @v send Event descriptor + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xenevent_send ( struct xen_hypervisor *xen, struct evtchn_send *send ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_event_channel_op, + EVTCHNOP_send, virt_to_phys ( send ) ); +} + +/** + * Allocate an unbound event channel + * + * @v xen Xen hypervisor + * @v alloc_unbound Event descriptor + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xenevent_alloc_unbound ( struct xen_hypervisor *xen, + struct evtchn_alloc_unbound *alloc_unbound ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_event_channel_op, + EVTCHNOP_alloc_unbound, + virt_to_phys ( alloc_unbound ) ); +} + +#endif /* _IPXE_XENEVENT_H */ diff --git a/src/include/ipxe/xengrant.h b/src/include/ipxe/xengrant.h new file mode 100644 index 000000000..776eb9273 --- /dev/null +++ b/src/include/ipxe/xengrant.h @@ -0,0 +1,102 @@ +#ifndef _IPXE_XENGRANT_H +#define _IPXE_XENGRANT_H + +/** @file + * + * Xen grant tables + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/io.h> +#include <ipxe/xen.h> +#include <xen/grant_table.h> + +/** + * Query grant table size + * + * @v xen Xen hypervisor + * @v size Table size + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xengrant_query_size ( struct xen_hypervisor *xen, + struct gnttab_query_size *size ) { + + return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op, + GNTTABOP_query_size, + virt_to_phys ( size ), 1 ); +} + +/** + * Set grant table version + * + * @v xen Xen hypervisor + * @v version Version + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xengrant_set_version ( struct xen_hypervisor *xen, + struct gnttab_set_version *version ) { + + return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op, + GNTTABOP_set_version, + virt_to_phys ( version ), 1 ); +} + +/** + * Invalidate access to a page + * + * @v xen Xen hypervisor + * @v ref Grant reference + */ +static inline __attribute__ (( always_inline )) void +xengrant_invalidate ( struct xen_hypervisor *xen, grant_ref_t ref ) { + union grant_entry_v2 *entry = &xen->grant.table[ref]; + + /* Sanity check */ + assert ( ( readw ( &entry->hdr.flags ) & + ( GTF_reading | GTF_writing ) ) == 0 ); + + /* This should apparently be done using a cmpxchg instruction. + * We omit this: partly in the interests of simplicity, but + * mainly since our control flow generally does not permit + * failure paths to themselves fail. + */ + writew ( 0, &entry->hdr.flags ); +} + +/** + * Permit access to a page + * + * @v xen Xen hypervisor + * @v ref Grant reference + * @v domid Domain ID + * @v subflags Additional flags + * @v page Page start + */ +static inline __attribute__ (( always_inline )) void +xengrant_permit_access ( struct xen_hypervisor *xen, grant_ref_t ref, + domid_t domid, unsigned int subflags, void *page ) { + union grant_entry_v2 *entry = &xen->grant.table[ref]; + unsigned long frame = ( virt_to_phys ( page ) / PAGE_SIZE ); + + writew ( domid, &entry->full_page.hdr.domid ); + if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) { + writeq ( frame, &entry->full_page.frame ); + } else { + writel ( frame, &entry->full_page.frame ); + } + wmb(); + writew ( ( GTF_permit_access | subflags ), &entry->full_page.hdr.flags); + wmb(); +} + +extern int xengrant_alloc ( struct xen_hypervisor *xen, grant_ref_t *refs, + unsigned int count ); +extern void xengrant_free ( struct xen_hypervisor *xen, grant_ref_t *refs, + unsigned int count ); + +#endif /* _IPXE_XENGRANT_H */ diff --git a/src/include/ipxe/xenmem.h b/src/include/ipxe/xenmem.h new file mode 100644 index 000000000..9b9aeda9c --- /dev/null +++ b/src/include/ipxe/xenmem.h @@ -0,0 +1,46 @@ +#ifndef _IPXE_XENMEM_H +#define _IPXE_XENMEM_H + +/** @file + * + * Xen memory operations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/xen.h> +#include <xen/memory.h> + +/** + * Add page to physical address space + * + * @v xen Xen hypervisor + * @v add Page mapping descriptor + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xenmem_add_to_physmap ( struct xen_hypervisor *xen, + struct xen_add_to_physmap *add ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_memory_op, + XENMEM_add_to_physmap, virt_to_phys ( add ) ); +} + +/** + * Remove page from physical address space + * + * @v xen Xen hypervisor + * @v remove Page mapping descriptor + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xenmem_remove_from_physmap ( struct xen_hypervisor *xen, + struct xen_remove_from_physmap *remove ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_memory_op, + XENMEM_remove_from_physmap, + virt_to_phys ( remove ) ); +} + +#endif /* _IPXE_XENMEM_H */ diff --git a/src/include/ipxe/xenstore.h b/src/include/ipxe/xenstore.h new file mode 100644 index 000000000..f25f15704 --- /dev/null +++ b/src/include/ipxe/xenstore.h @@ -0,0 +1,29 @@ +#ifndef _IPXE_XENSTORE_H +#define _IPXE_XENSTORE_H + +/** @file + * + * XenStore interface + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/xen.h> + +extern __attribute__ (( sentinel )) int +xenstore_read ( struct xen_hypervisor *xen, char **value, ... ); +extern __attribute__ (( sentinel )) int +xenstore_read_num ( struct xen_hypervisor *xen, unsigned long *num, ... ); +extern __attribute__ (( sentinel )) int +xenstore_write ( struct xen_hypervisor *xen, const char *value, ... ); +extern __attribute__ (( sentinel )) int +xenstore_write_num ( struct xen_hypervisor *xen, unsigned long num, ... ); +extern __attribute__ (( sentinel )) int +xenstore_rm ( struct xen_hypervisor *xen, ... ); +extern __attribute__ (( sentinel )) int +xenstore_directory ( struct xen_hypervisor *xen, char **children, size_t *len, + ... ); +extern void xenstore_dump ( struct xen_hypervisor *xen, const char *key ); + +#endif /* _IPXE_XENSTORE_H */ diff --git a/src/include/ipxe/xenver.h b/src/include/ipxe/xenver.h new file mode 100644 index 000000000..5d678c5a3 --- /dev/null +++ b/src/include/ipxe/xenver.h @@ -0,0 +1,44 @@ +#ifndef _IPXE_XENVER_H +#define _IPXE_VENVER_H + +/** @file + * + * Xen version + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/xen.h> +#include <xen/version.h> + +/** + * Get Xen version + * + * @v xen Xen hypervisor + * @ret version Version (major.minor: 16 bits each) + */ +static inline __attribute__ (( always_inline )) uint32 +xenver_version ( struct xen_hypervisor *xen ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_xen_version, + XENVER_version, 0 ); +} + +/** + * Get Xen extra version string + * + * @v xen Xen hypervisor + * @v extraversion Extra version string to fill in + * @ret xenrc Xen status code + */ +static inline __attribute__ (( always_inline )) int +xenver_extraversion ( struct xen_hypervisor *xen, + xen_extraversion_t *extraversion ) { + + return xen_hypercall_2 ( xen, __HYPERVISOR_xen_version, + XENVER_extraversion, + virt_to_phys ( extraversion ) ); +} + +#endif /* _IPXE_XENVER_H */ |