Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / xengrant.h
diff --git a/qemu/roms/ipxe/src/include/ipxe/xengrant.h b/qemu/roms/ipxe/src/include/ipxe/xengrant.h
new file mode 100644 (file)
index 0000000..f9b3beb
--- /dev/null
@@ -0,0 +1,232 @@
+#ifndef _IPXE_XENGRANT_H
+#define _IPXE_XENGRANT_H
+
+/** @file
+ *
+ * Xen grant tables
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <ipxe/io.h>
+#include <ipxe/xen.h>
+#include <xen/grant_table.h>
+
+/** Induced failure rate (for testing) */
+#define XENGRANT_FAIL_RATE 0
+
+/**
+ * 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 );
+}
+
+/**
+ * Get grant table version
+ *
+ * @v xen              Xen hypervisor
+ * @v version          Version
+ * @ret xenrc          Xen status code
+ */
+static inline __attribute__ (( always_inline )) int
+xengrant_get_version ( struct xen_hypervisor *xen,
+                      struct gnttab_get_version *version ) {
+
+       return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
+                                GNTTABOP_get_version,
+                                virt_to_phys ( version ), 1 );
+}
+
+/**
+ * Get number of grant table entries
+ *
+ * @v xen              Xen hypervisor
+ * @ret entries                Number of grant table entries
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+xengrant_entries ( struct xen_hypervisor *xen ) {
+
+       return ( ( xen->grant.len / sizeof ( xen->grant.table[0] ) )
+                >> xen->grant.shift );
+}
+
+/**
+ * Get grant table entry header
+ *
+ * @v xen              Xen hypervisor
+ * @v ref              Grant reference
+ * @ret hdr            Grant table entry header
+ */
+static inline __attribute__ (( always_inline )) struct grant_entry_header *
+xengrant_header ( struct xen_hypervisor *xen, grant_ref_t ref ) {
+       struct grant_entry_v1 *v1;
+
+       v1 = &xen->grant.table[ ref << xen->grant.shift ];
+       return ( container_of ( &v1->flags, struct grant_entry_header, flags ));
+}
+
+/**
+ * Get version 1 grant table entry
+ *
+ * @v hdr              Grant table entry header
+ * @ret v1             Version 1 grant table entry
+ */
+static inline __attribute__ (( always_inline )) struct grant_entry_v1 *
+xengrant_v1 ( struct grant_entry_header *hdr ) {
+
+       return ( container_of ( &hdr->flags, struct grant_entry_v1, flags ) );
+}
+
+/**
+ * Get version 2 grant table entry
+ *
+ * @v hdr              Grant table entry header
+ * @ret v2             Version 2 grant table entry
+ */
+static inline __attribute__ (( always_inline )) union grant_entry_v2 *
+xengrant_v2 ( struct grant_entry_header *hdr ) {
+
+       return ( container_of ( &hdr->flags, union grant_entry_v2, hdr.flags ));
+}
+
+/**
+ * Zero grant table entry
+ *
+ * @v xen              Xen hypervisor
+ * @v hdr              Grant table entry header
+ */
+static inline void xengrant_zero ( struct xen_hypervisor *xen,
+                                  struct grant_entry_header *hdr ) {
+       uint32_t *dword = ( ( uint32_t * ) hdr );
+       unsigned int i = ( ( sizeof ( xen->grant.table[0] ) / sizeof ( *dword ))
+                          << xen->grant.shift );
+
+       while ( i-- )
+               writel ( 0, dword++ );
+}
+
+/**
+ * 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 ) {
+       struct grant_entry_header *hdr = xengrant_header ( xen, ref );
+
+       /* Sanity check */
+       assert ( ( readw ( &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, &hdr->flags );
+
+       /* Leave reference marked as in-use (see xengrant_alloc()) */
+       writew ( DOMID_SELF, &hdr->domid );
+}
+
+/**
+ * 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
+ * @ret rc             Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+xengrant_permit_access ( struct xen_hypervisor *xen, grant_ref_t ref,
+                        domid_t domid, unsigned int subflags, void *page ) {
+       struct grant_entry_header *hdr = xengrant_header ( xen, ref );
+       struct grant_entry_v1 *v1 = xengrant_v1 ( hdr );
+       union grant_entry_v2 *v2 = xengrant_v2 ( hdr );
+       unsigned long frame = ( virt_to_phys ( page ) / PAGE_SIZE );
+
+       /* Fail (for test purposes) if applicable */
+       if ( ( XENGRANT_FAIL_RATE > 0 ) &&
+            ( random() % XENGRANT_FAIL_RATE ) == 0 ) {
+               return -EAGAIN;
+       }
+
+       /* Record frame number.  This may fail on a 64-bit system if
+        * we are using v1 grant tables.  On a 32-bit system, there is
+        * no way for this code path to fail (with either v1 or v2
+        * grant tables); we allow the compiler to optimise the
+        * failure paths away to save space.
+        */
+       if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) {
+
+               /* 64-bit system */
+               if ( xen->grant.shift ) {
+                       /* Version 2 table: no possible failure */
+                       writeq ( frame, &v2->full_page.frame );
+               } else {
+                       /* Version 1 table: may fail if address above 16TB */
+                       if ( frame > 0xffffffffUL )
+                               return -ERANGE;
+                       writel ( frame, &v1->frame );
+               }
+
+       } else {
+
+               /* 32-bit system */
+               if ( xen->grant.shift ) {
+                       /* Version 2 table: no possible failure */
+                       writel ( frame, &v2->full_page.frame );
+               } else {
+                       /* Version 1 table: no possible failure */
+                       writel ( frame, &v1->frame );
+               }
+       }
+
+       /* Record domain ID and flags */
+       writew ( domid, &hdr->domid );
+       wmb();
+       writew ( ( GTF_permit_access | subflags ), &hdr->flags );
+       wmb();
+
+       return 0;
+}
+
+extern int xengrant_init ( struct xen_hypervisor *xen );
+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 */