You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #ifndef _IPXE_XENGRANT_H
  2. #define _IPXE_XENGRANT_H
  3. /** @file
  4. *
  5. * Xen grant tables
  6. *
  7. */
  8. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  9. #include <stdint.h>
  10. #include <stdlib.h>
  11. #include <ipxe/io.h>
  12. #include <ipxe/xen.h>
  13. #include <xen/grant_table.h>
  14. /** Induced failure rate (for testing) */
  15. #define XENGRANT_FAIL_RATE 0
  16. /**
  17. * Query grant table size
  18. *
  19. * @v xen Xen hypervisor
  20. * @v size Table size
  21. * @ret xenrc Xen status code
  22. */
  23. static inline __attribute__ (( always_inline )) int
  24. xengrant_query_size ( struct xen_hypervisor *xen,
  25. struct gnttab_query_size *size ) {
  26. return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
  27. GNTTABOP_query_size,
  28. virt_to_phys ( size ), 1 );
  29. }
  30. /**
  31. * Set grant table version
  32. *
  33. * @v xen Xen hypervisor
  34. * @v version Version
  35. * @ret xenrc Xen status code
  36. */
  37. static inline __attribute__ (( always_inline )) int
  38. xengrant_set_version ( struct xen_hypervisor *xen,
  39. struct gnttab_set_version *version ) {
  40. return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
  41. GNTTABOP_set_version,
  42. virt_to_phys ( version ), 1 );
  43. }
  44. /**
  45. * Get grant table version
  46. *
  47. * @v xen Xen hypervisor
  48. * @v version Version
  49. * @ret xenrc Xen status code
  50. */
  51. static inline __attribute__ (( always_inline )) int
  52. xengrant_get_version ( struct xen_hypervisor *xen,
  53. struct gnttab_get_version *version ) {
  54. return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
  55. GNTTABOP_get_version,
  56. virt_to_phys ( version ), 1 );
  57. }
  58. /**
  59. * Get number of grant table entries
  60. *
  61. * @v xen Xen hypervisor
  62. * @ret entries Number of grant table entries
  63. */
  64. static inline __attribute__ (( always_inline )) unsigned int
  65. xengrant_entries ( struct xen_hypervisor *xen ) {
  66. return ( ( xen->grant.len / sizeof ( xen->grant.table[0] ) )
  67. >> xen->grant.shift );
  68. }
  69. /**
  70. * Get grant table entry header
  71. *
  72. * @v xen Xen hypervisor
  73. * @v ref Grant reference
  74. * @ret hdr Grant table entry header
  75. */
  76. static inline __attribute__ (( always_inline )) struct grant_entry_header *
  77. xengrant_header ( struct xen_hypervisor *xen, grant_ref_t ref ) {
  78. struct grant_entry_v1 *v1;
  79. v1 = &xen->grant.table[ ref << xen->grant.shift ];
  80. return ( container_of ( &v1->flags, struct grant_entry_header, flags ));
  81. }
  82. /**
  83. * Get version 1 grant table entry
  84. *
  85. * @v hdr Grant table entry header
  86. * @ret v1 Version 1 grant table entry
  87. */
  88. static inline __attribute__ (( always_inline )) struct grant_entry_v1 *
  89. xengrant_v1 ( struct grant_entry_header *hdr ) {
  90. return ( container_of ( &hdr->flags, struct grant_entry_v1, flags ) );
  91. }
  92. /**
  93. * Get version 2 grant table entry
  94. *
  95. * @v hdr Grant table entry header
  96. * @ret v2 Version 2 grant table entry
  97. */
  98. static inline __attribute__ (( always_inline )) union grant_entry_v2 *
  99. xengrant_v2 ( struct grant_entry_header *hdr ) {
  100. return ( container_of ( &hdr->flags, union grant_entry_v2, hdr.flags ));
  101. }
  102. /**
  103. * Zero grant table entry
  104. *
  105. * @v xen Xen hypervisor
  106. * @v hdr Grant table entry header
  107. */
  108. static inline void xengrant_zero ( struct xen_hypervisor *xen,
  109. struct grant_entry_header *hdr ) {
  110. uint32_t *dword = ( ( uint32_t * ) hdr );
  111. unsigned int i = ( ( sizeof ( xen->grant.table[0] ) / sizeof ( *dword ))
  112. << xen->grant.shift );
  113. while ( i-- )
  114. writel ( 0, dword++ );
  115. }
  116. /**
  117. * Invalidate access to a page
  118. *
  119. * @v xen Xen hypervisor
  120. * @v ref Grant reference
  121. */
  122. static inline __attribute__ (( always_inline )) void
  123. xengrant_invalidate ( struct xen_hypervisor *xen, grant_ref_t ref ) {
  124. struct grant_entry_header *hdr = xengrant_header ( xen, ref );
  125. /* Sanity check */
  126. assert ( ( readw ( &hdr->flags ) &
  127. ( GTF_reading | GTF_writing ) ) == 0 );
  128. /* This should apparently be done using a cmpxchg instruction.
  129. * We omit this: partly in the interests of simplicity, but
  130. * mainly since our control flow generally does not permit
  131. * failure paths to themselves fail.
  132. */
  133. writew ( 0, &hdr->flags );
  134. /* Leave reference marked as in-use (see xengrant_alloc()) */
  135. writew ( DOMID_SELF, &hdr->domid );
  136. }
  137. /**
  138. * Permit access to a page
  139. *
  140. * @v xen Xen hypervisor
  141. * @v ref Grant reference
  142. * @v domid Domain ID
  143. * @v subflags Additional flags
  144. * @v page Page start
  145. * @ret rc Return status code
  146. */
  147. static inline __attribute__ (( always_inline )) int
  148. xengrant_permit_access ( struct xen_hypervisor *xen, grant_ref_t ref,
  149. domid_t domid, unsigned int subflags, void *page ) {
  150. struct grant_entry_header *hdr = xengrant_header ( xen, ref );
  151. struct grant_entry_v1 *v1 = xengrant_v1 ( hdr );
  152. union grant_entry_v2 *v2 = xengrant_v2 ( hdr );
  153. unsigned long frame = ( virt_to_phys ( page ) / PAGE_SIZE );
  154. /* Fail (for test purposes) if applicable */
  155. if ( ( XENGRANT_FAIL_RATE > 0 ) &&
  156. ( random() % XENGRANT_FAIL_RATE ) == 0 ) {
  157. return -EAGAIN;
  158. }
  159. /* Record frame number. This may fail on a 64-bit system if
  160. * we are using v1 grant tables. On a 32-bit system, there is
  161. * no way for this code path to fail (with either v1 or v2
  162. * grant tables); we allow the compiler to optimise the
  163. * failure paths away to save space.
  164. */
  165. if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) {
  166. /* 64-bit system */
  167. if ( xen->grant.shift ) {
  168. /* Version 2 table: no possible failure */
  169. writeq ( frame, &v2->full_page.frame );
  170. } else {
  171. /* Version 1 table: may fail if address above 16TB */
  172. if ( frame > 0xffffffffUL )
  173. return -ERANGE;
  174. writel ( frame, &v1->frame );
  175. }
  176. } else {
  177. /* 32-bit system */
  178. if ( xen->grant.shift ) {
  179. /* Version 2 table: no possible failure */
  180. writel ( frame, &v2->full_page.frame );
  181. } else {
  182. /* Version 1 table: no possible failure */
  183. writel ( frame, &v1->frame );
  184. }
  185. }
  186. /* Record domain ID and flags */
  187. writew ( domid, &hdr->domid );
  188. wmb();
  189. writew ( ( GTF_permit_access | subflags ), &hdr->flags );
  190. wmb();
  191. return 0;
  192. }
  193. extern int xengrant_init ( struct xen_hypervisor *xen );
  194. extern int xengrant_alloc ( struct xen_hypervisor *xen, grant_ref_t *refs,
  195. unsigned int count );
  196. extern void xengrant_free ( struct xen_hypervisor *xen, grant_ref_t *refs,
  197. unsigned int count );
  198. #endif /* _IPXE_XENGRANT_H */