mirror of
https://github.com/ipxe/ipxe
synced 2025-12-24 15:23:42 +03:00
[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>
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
73
src/include/ipxe/xen.h
Normal file
73
src/include/ipxe/xen.h
Normal file
@@ -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 */
|
||||
85
src/include/ipxe/xenbus.h
Normal file
85
src/include/ipxe/xenbus.h
Normal file
@@ -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 */
|
||||
59
src/include/ipxe/xenevent.h
Normal file
59
src/include/ipxe/xenevent.h
Normal file
@@ -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 */
|
||||
102
src/include/ipxe/xengrant.h
Normal file
102
src/include/ipxe/xengrant.h
Normal file
@@ -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 */
|
||||
46
src/include/ipxe/xenmem.h
Normal file
46
src/include/ipxe/xenmem.h
Normal file
@@ -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 */
|
||||
29
src/include/ipxe/xenstore.h
Normal file
29
src/include/ipxe/xenstore.h
Normal file
@@ -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 */
|
||||
44
src/include/ipxe/xenver.h
Normal file
44
src/include/ipxe/xenver.h
Normal file
@@ -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 */
|
||||
Reference in New Issue
Block a user