summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe
diff options
context:
space:
mode:
authorMichael Brown2014-07-29 00:38:30 +0200
committerMichael Brown2014-07-29 16:57:44 +0200
commit036af27a4523c4e15e28d30a1513a3f6d9671774 (patch)
treebf284637f91e2258906d736f07a54b1f98dfd68d /src/include/ipxe
parent[xen] Import selected public headers (diff)
downloadipxe-036af27a4523c4e15e28d30a1513a3f6d9671774.tar.gz
ipxe-036af27a4523c4e15e28d30a1513a3f6d9671774.tar.xz
ipxe-036af27a4523c4e15e28d30a1513a3f6d9671774.zip
[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/ipxe')
-rw-r--r--src/include/ipxe/device.h3
-rw-r--r--src/include/ipxe/errfile.h3
-rw-r--r--src/include/ipxe/xen.h73
-rw-r--r--src/include/ipxe/xenbus.h85
-rw-r--r--src/include/ipxe/xenevent.h59
-rw-r--r--src/include/ipxe/xengrant.h102
-rw-r--r--src/include/ipxe/xenmem.h46
-rw-r--r--src/include/ipxe/xenstore.h29
-rw-r--r--src/include/ipxe/xenver.h44
9 files changed, 444 insertions, 0 deletions
diff --git a/src/include/ipxe/device.h b/src/include/ipxe/device.h
index 89509734..7202a696 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 a8b3a8e4..3fa499dd 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 00000000..546b0c34
--- /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 00000000..2777226f
--- /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 00000000..1dd6a0c0
--- /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 00000000..776eb927
--- /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 00000000..9b9aeda9
--- /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 00000000..f25f1570
--- /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 00000000..5d678c5a
--- /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 */