1 #ifndef _IPXE_XENGRANT_H
2 #define _IPXE_XENGRANT_H
10 FILE_LICENCE ( GPL2_OR_LATER );
16 #include <xen/grant_table.h>
18 /** Induced failure rate (for testing) */
19 #define XENGRANT_FAIL_RATE 0
22 * Query grant table size
24 * @v xen Xen hypervisor
26 * @ret xenrc Xen status code
28 static inline __attribute__ (( always_inline )) int
29 xengrant_query_size ( struct xen_hypervisor *xen,
30 struct gnttab_query_size *size ) {
32 return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
34 virt_to_phys ( size ), 1 );
38 * Set grant table version
40 * @v xen Xen hypervisor
42 * @ret xenrc Xen status code
44 static inline __attribute__ (( always_inline )) int
45 xengrant_set_version ( struct xen_hypervisor *xen,
46 struct gnttab_set_version *version ) {
48 return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
50 virt_to_phys ( version ), 1 );
54 * Get grant table version
56 * @v xen Xen hypervisor
58 * @ret xenrc Xen status code
60 static inline __attribute__ (( always_inline )) int
61 xengrant_get_version ( struct xen_hypervisor *xen,
62 struct gnttab_get_version *version ) {
64 return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
66 virt_to_phys ( version ), 1 );
70 * Get number of grant table entries
72 * @v xen Xen hypervisor
73 * @ret entries Number of grant table entries
75 static inline __attribute__ (( always_inline )) unsigned int
76 xengrant_entries ( struct xen_hypervisor *xen ) {
78 return ( ( xen->grant.len / sizeof ( xen->grant.table[0] ) )
79 >> xen->grant.shift );
83 * Get grant table entry header
85 * @v xen Xen hypervisor
86 * @v ref Grant reference
87 * @ret hdr Grant table entry header
89 static inline __attribute__ (( always_inline )) struct grant_entry_header *
90 xengrant_header ( struct xen_hypervisor *xen, grant_ref_t ref ) {
91 struct grant_entry_v1 *v1;
93 v1 = &xen->grant.table[ ref << xen->grant.shift ];
94 return ( container_of ( &v1->flags, struct grant_entry_header, flags ));
98 * Get version 1 grant table entry
100 * @v hdr Grant table entry header
101 * @ret v1 Version 1 grant table entry
103 static inline __attribute__ (( always_inline )) struct grant_entry_v1 *
104 xengrant_v1 ( struct grant_entry_header *hdr ) {
106 return ( container_of ( &hdr->flags, struct grant_entry_v1, flags ) );
110 * Get version 2 grant table entry
112 * @v hdr Grant table entry header
113 * @ret v2 Version 2 grant table entry
115 static inline __attribute__ (( always_inline )) union grant_entry_v2 *
116 xengrant_v2 ( struct grant_entry_header *hdr ) {
118 return ( container_of ( &hdr->flags, union grant_entry_v2, hdr.flags ));
122 * Zero grant table entry
124 * @v xen Xen hypervisor
125 * @v hdr Grant table entry header
127 static inline void xengrant_zero ( struct xen_hypervisor *xen,
128 struct grant_entry_header *hdr ) {
129 uint32_t *dword = ( ( uint32_t * ) hdr );
130 unsigned int i = ( ( sizeof ( xen->grant.table[0] ) / sizeof ( *dword ))
131 << xen->grant.shift );
134 writel ( 0, dword++ );
138 * Invalidate access to a page
140 * @v xen Xen hypervisor
141 * @v ref Grant reference
143 static inline __attribute__ (( always_inline )) void
144 xengrant_invalidate ( struct xen_hypervisor *xen, grant_ref_t ref ) {
145 struct grant_entry_header *hdr = xengrant_header ( xen, ref );
148 assert ( ( readw ( &hdr->flags ) &
149 ( GTF_reading | GTF_writing ) ) == 0 );
151 /* This should apparently be done using a cmpxchg instruction.
152 * We omit this: partly in the interests of simplicity, but
153 * mainly since our control flow generally does not permit
154 * failure paths to themselves fail.
156 writew ( 0, &hdr->flags );
158 /* Leave reference marked as in-use (see xengrant_alloc()) */
159 writew ( DOMID_SELF, &hdr->domid );
163 * Permit access to a page
165 * @v xen Xen hypervisor
166 * @v ref Grant reference
168 * @v subflags Additional flags
170 * @ret rc Return status code
172 static inline __attribute__ (( always_inline )) int
173 xengrant_permit_access ( struct xen_hypervisor *xen, grant_ref_t ref,
174 domid_t domid, unsigned int subflags, void *page ) {
175 struct grant_entry_header *hdr = xengrant_header ( xen, ref );
176 struct grant_entry_v1 *v1 = xengrant_v1 ( hdr );
177 union grant_entry_v2 *v2 = xengrant_v2 ( hdr );
178 unsigned long frame = ( virt_to_phys ( page ) / PAGE_SIZE );
180 /* Fail (for test purposes) if applicable */
181 if ( ( XENGRANT_FAIL_RATE > 0 ) &&
182 ( random() % XENGRANT_FAIL_RATE ) == 0 ) {
186 /* Record frame number. This may fail on a 64-bit system if
187 * we are using v1 grant tables. On a 32-bit system, there is
188 * no way for this code path to fail (with either v1 or v2
189 * grant tables); we allow the compiler to optimise the
190 * failure paths away to save space.
192 if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) {
195 if ( xen->grant.shift ) {
196 /* Version 2 table: no possible failure */
197 writeq ( frame, &v2->full_page.frame );
199 /* Version 1 table: may fail if address above 16TB */
200 if ( frame > 0xffffffffUL )
202 writel ( frame, &v1->frame );
208 if ( xen->grant.shift ) {
209 /* Version 2 table: no possible failure */
210 writel ( frame, &v2->full_page.frame );
212 /* Version 1 table: no possible failure */
213 writel ( frame, &v1->frame );
217 /* Record domain ID and flags */
218 writew ( domid, &hdr->domid );
220 writew ( ( GTF_permit_access | subflags ), &hdr->flags );
226 extern int xengrant_init ( struct xen_hypervisor *xen );
227 extern int xengrant_alloc ( struct xen_hypervisor *xen, grant_ref_t *refs,
228 unsigned int count );
229 extern void xengrant_free ( struct xen_hypervisor *xen, grant_ref_t *refs,
230 unsigned int count );
232 #endif /* _IPXE_XENGRANT_H */