iPXE
xengrant.h
Go to the documentation of this file.
00001 #ifndef _IPXE_XENGRANT_H
00002 #define _IPXE_XENGRANT_H
00003 
00004 /** @file
00005  *
00006  * Xen grant tables
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <stdint.h>
00013 #include <stdlib.h>
00014 #include <ipxe/io.h>
00015 #include <ipxe/xen.h>
00016 #include <xen/grant_table.h>
00017 
00018 /** Induced failure rate (for testing) */
00019 #define XENGRANT_FAIL_RATE 0
00020 
00021 /**
00022  * Query grant table size
00023  *
00024  * @v xen               Xen hypervisor
00025  * @v size              Table size
00026  * @ret xenrc           Xen status code
00027  */
00028 static inline __attribute__ (( always_inline )) int
00029 xengrant_query_size ( struct xen_hypervisor *xen,
00030                       struct gnttab_query_size *size ) {
00031 
00032         return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
00033                                  GNTTABOP_query_size,
00034                                  virt_to_phys ( size ), 1 );
00035 }
00036 
00037 /**
00038  * Set grant table version
00039  *
00040  * @v xen               Xen hypervisor
00041  * @v version           Version
00042  * @ret xenrc           Xen status code
00043  */
00044 static inline __attribute__ (( always_inline )) int
00045 xengrant_set_version ( struct xen_hypervisor *xen,
00046                        struct gnttab_set_version *version ) {
00047 
00048         return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
00049                                  GNTTABOP_set_version,
00050                                  virt_to_phys ( version ), 1 );
00051 }
00052 
00053 /**
00054  * Get grant table version
00055  *
00056  * @v xen               Xen hypervisor
00057  * @v version           Version
00058  * @ret xenrc           Xen status code
00059  */
00060 static inline __attribute__ (( always_inline )) int
00061 xengrant_get_version ( struct xen_hypervisor *xen,
00062                        struct gnttab_get_version *version ) {
00063 
00064         return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
00065                                  GNTTABOP_get_version,
00066                                  virt_to_phys ( version ), 1 );
00067 }
00068 
00069 /**
00070  * Get number of grant table entries
00071  *
00072  * @v xen               Xen hypervisor
00073  * @ret entries         Number of grant table entries
00074  */
00075 static inline __attribute__ (( always_inline )) unsigned int
00076 xengrant_entries ( struct xen_hypervisor *xen ) {
00077 
00078         return ( ( xen->grant.len / sizeof ( xen->grant.table[0] ) )
00079                  >> xen->grant.shift );
00080 }
00081 
00082 /**
00083  * Get grant table entry header
00084  *
00085  * @v xen               Xen hypervisor
00086  * @v ref               Grant reference
00087  * @ret hdr             Grant table entry header
00088  */
00089 static inline __attribute__ (( always_inline )) struct grant_entry_header *
00090 xengrant_header ( struct xen_hypervisor *xen, grant_ref_t ref ) {
00091         struct grant_entry_v1 *v1;
00092 
00093         v1 = &xen->grant.table[ ref << xen->grant.shift ];
00094         return ( container_of ( &v1->flags, struct grant_entry_header, flags ));
00095 }
00096 
00097 /**
00098  * Get version 1 grant table entry
00099  *
00100  * @v hdr               Grant table entry header
00101  * @ret v1              Version 1 grant table entry
00102  */
00103 static inline __attribute__ (( always_inline )) struct grant_entry_v1 *
00104 xengrant_v1 ( struct grant_entry_header *hdr ) {
00105 
00106         return ( container_of ( &hdr->flags, struct grant_entry_v1, flags ) );
00107 }
00108 
00109 /**
00110  * Get version 2 grant table entry
00111  *
00112  * @v hdr               Grant table entry header
00113  * @ret v2              Version 2 grant table entry
00114  */
00115 static inline __attribute__ (( always_inline )) union grant_entry_v2 *
00116 xengrant_v2 ( struct grant_entry_header *hdr ) {
00117 
00118         return ( container_of ( &hdr->flags, union grant_entry_v2, hdr.flags ));
00119 }
00120 
00121 /**
00122  * Zero grant table entry
00123  *
00124  * @v xen               Xen hypervisor
00125  * @v hdr               Grant table entry header
00126  */
00127 static inline void xengrant_zero ( struct xen_hypervisor *xen,
00128                                    struct grant_entry_header *hdr ) {
00129         uint32_t *dword = ( ( uint32_t * ) hdr );
00130         unsigned int i = ( ( sizeof ( xen->grant.table[0] ) / sizeof ( *dword ))
00131                            << xen->grant.shift );
00132 
00133         while ( i-- )
00134                 writel ( 0, dword++ );
00135 }
00136 
00137 /**
00138  * Invalidate access to a page
00139  *
00140  * @v xen               Xen hypervisor
00141  * @v ref               Grant reference
00142  */
00143 static inline __attribute__ (( always_inline )) void
00144 xengrant_invalidate ( struct xen_hypervisor *xen, grant_ref_t ref ) {
00145         struct grant_entry_header *hdr = xengrant_header ( xen, ref );
00146 
00147         /* Sanity check */
00148         assert ( ( readw ( &hdr->flags ) &
00149                    ( GTF_reading | GTF_writing ) ) == 0 );
00150 
00151         /* This should apparently be done using a cmpxchg instruction.
00152          * We omit this: partly in the interests of simplicity, but
00153          * mainly since our control flow generally does not permit
00154          * failure paths to themselves fail.
00155          */
00156         writew ( 0, &hdr->flags );
00157 
00158         /* Leave reference marked as in-use (see xengrant_alloc()) */
00159         writew ( DOMID_SELF, &hdr->domid );
00160 }
00161 
00162 /**
00163  * Permit access to a page
00164  *
00165  * @v xen               Xen hypervisor
00166  * @v ref               Grant reference
00167  * @v domid             Domain ID
00168  * @v subflags          Additional flags
00169  * @v page              Page start
00170  * @ret rc              Return status code
00171  */
00172 static inline __attribute__ (( always_inline )) int
00173 xengrant_permit_access ( struct xen_hypervisor *xen, grant_ref_t ref,
00174                          domid_t domid, unsigned int subflags, void *page ) {
00175         struct grant_entry_header *hdr = xengrant_header ( xen, ref );
00176         struct grant_entry_v1 *v1 = xengrant_v1 ( hdr );
00177         union grant_entry_v2 *v2 = xengrant_v2 ( hdr );
00178         unsigned long frame = ( virt_to_phys ( page ) / PAGE_SIZE );
00179 
00180         /* Fail (for test purposes) if applicable */
00181         if ( ( XENGRANT_FAIL_RATE > 0 ) &&
00182              ( random() % XENGRANT_FAIL_RATE ) == 0 ) {
00183                 return -EAGAIN;
00184         }
00185 
00186         /* Record frame number.  This may fail on a 64-bit system if
00187          * we are using v1 grant tables.  On a 32-bit system, there is
00188          * no way for this code path to fail (with either v1 or v2
00189          * grant tables); we allow the compiler to optimise the
00190          * failure paths away to save space.
00191          */
00192         if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) {
00193 
00194                 /* 64-bit system */
00195                 if ( xen->grant.shift ) {
00196                         /* Version 2 table: no possible failure */
00197                         writeq ( frame, &v2->full_page.frame );
00198                 } else {
00199                         /* Version 1 table: may fail if address above 16TB */
00200                         if ( frame > 0xffffffffUL )
00201                                 return -ERANGE;
00202                         writel ( frame, &v1->frame );
00203                 }
00204 
00205         } else {
00206 
00207                 /* 32-bit system */
00208                 if ( xen->grant.shift ) {
00209                         /* Version 2 table: no possible failure */
00210                         writel ( frame, &v2->full_page.frame );
00211                 } else {
00212                         /* Version 1 table: no possible failure */
00213                         writel ( frame, &v1->frame );
00214                 }
00215         }
00216 
00217         /* Record domain ID and flags */
00218         writew ( domid, &hdr->domid );
00219         wmb();
00220         writew ( ( GTF_permit_access | subflags ), &hdr->flags );
00221         wmb();
00222 
00223         return 0;
00224 }
00225 
00226 extern int xengrant_init ( struct xen_hypervisor *xen );
00227 extern int xengrant_alloc ( struct xen_hypervisor *xen, grant_ref_t *refs,
00228                             unsigned int count );
00229 extern void xengrant_free ( struct xen_hypervisor *xen, grant_ref_t *refs,
00230                             unsigned int count );
00231 
00232 #endif /* _IPXE_XENGRANT_H */