Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / xengrant.h
1 #ifndef _IPXE_XENGRANT_H
2 #define _IPXE_XENGRANT_H
3
4 /** @file
5  *
6  * Xen grant tables
7  *
8  */
9
10 FILE_LICENCE ( GPL2_OR_LATER );
11
12 #include <stdint.h>
13 #include <stdlib.h>
14 #include <ipxe/io.h>
15 #include <ipxe/xen.h>
16 #include <xen/grant_table.h>
17
18 /** Induced failure rate (for testing) */
19 #define XENGRANT_FAIL_RATE 0
20
21 /**
22  * Query grant table size
23  *
24  * @v xen               Xen hypervisor
25  * @v size              Table size
26  * @ret xenrc           Xen status code
27  */
28 static inline __attribute__ (( always_inline )) int
29 xengrant_query_size ( struct xen_hypervisor *xen,
30                       struct gnttab_query_size *size ) {
31
32         return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
33                                  GNTTABOP_query_size,
34                                  virt_to_phys ( size ), 1 );
35 }
36
37 /**
38  * Set grant table version
39  *
40  * @v xen               Xen hypervisor
41  * @v version           Version
42  * @ret xenrc           Xen status code
43  */
44 static inline __attribute__ (( always_inline )) int
45 xengrant_set_version ( struct xen_hypervisor *xen,
46                        struct gnttab_set_version *version ) {
47
48         return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
49                                  GNTTABOP_set_version,
50                                  virt_to_phys ( version ), 1 );
51 }
52
53 /**
54  * Get grant table version
55  *
56  * @v xen               Xen hypervisor
57  * @v version           Version
58  * @ret xenrc           Xen status code
59  */
60 static inline __attribute__ (( always_inline )) int
61 xengrant_get_version ( struct xen_hypervisor *xen,
62                        struct gnttab_get_version *version ) {
63
64         return xen_hypercall_3 ( xen, __HYPERVISOR_grant_table_op,
65                                  GNTTABOP_get_version,
66                                  virt_to_phys ( version ), 1 );
67 }
68
69 /**
70  * Get number of grant table entries
71  *
72  * @v xen               Xen hypervisor
73  * @ret entries         Number of grant table entries
74  */
75 static inline __attribute__ (( always_inline )) unsigned int
76 xengrant_entries ( struct xen_hypervisor *xen ) {
77
78         return ( ( xen->grant.len / sizeof ( xen->grant.table[0] ) )
79                  >> xen->grant.shift );
80 }
81
82 /**
83  * Get grant table entry header
84  *
85  * @v xen               Xen hypervisor
86  * @v ref               Grant reference
87  * @ret hdr             Grant table entry header
88  */
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;
92
93         v1 = &xen->grant.table[ ref << xen->grant.shift ];
94         return ( container_of ( &v1->flags, struct grant_entry_header, flags ));
95 }
96
97 /**
98  * Get version 1 grant table entry
99  *
100  * @v hdr               Grant table entry header
101  * @ret v1              Version 1 grant table entry
102  */
103 static inline __attribute__ (( always_inline )) struct grant_entry_v1 *
104 xengrant_v1 ( struct grant_entry_header *hdr ) {
105
106         return ( container_of ( &hdr->flags, struct grant_entry_v1, flags ) );
107 }
108
109 /**
110  * Get version 2 grant table entry
111  *
112  * @v hdr               Grant table entry header
113  * @ret v2              Version 2 grant table entry
114  */
115 static inline __attribute__ (( always_inline )) union grant_entry_v2 *
116 xengrant_v2 ( struct grant_entry_header *hdr ) {
117
118         return ( container_of ( &hdr->flags, union grant_entry_v2, hdr.flags ));
119 }
120
121 /**
122  * Zero grant table entry
123  *
124  * @v xen               Xen hypervisor
125  * @v hdr               Grant table entry header
126  */
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 );
132
133         while ( i-- )
134                 writel ( 0, dword++ );
135 }
136
137 /**
138  * Invalidate access to a page
139  *
140  * @v xen               Xen hypervisor
141  * @v ref               Grant reference
142  */
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 );
146
147         /* Sanity check */
148         assert ( ( readw ( &hdr->flags ) &
149                    ( GTF_reading | GTF_writing ) ) == 0 );
150
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.
155          */
156         writew ( 0, &hdr->flags );
157
158         /* Leave reference marked as in-use (see xengrant_alloc()) */
159         writew ( DOMID_SELF, &hdr->domid );
160 }
161
162 /**
163  * Permit access to a page
164  *
165  * @v xen               Xen hypervisor
166  * @v ref               Grant reference
167  * @v domid             Domain ID
168  * @v subflags          Additional flags
169  * @v page              Page start
170  * @ret rc              Return status code
171  */
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 );
179
180         /* Fail (for test purposes) if applicable */
181         if ( ( XENGRANT_FAIL_RATE > 0 ) &&
182              ( random() % XENGRANT_FAIL_RATE ) == 0 ) {
183                 return -EAGAIN;
184         }
185
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.
191          */
192         if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) {
193
194                 /* 64-bit system */
195                 if ( xen->grant.shift ) {
196                         /* Version 2 table: no possible failure */
197                         writeq ( frame, &v2->full_page.frame );
198                 } else {
199                         /* Version 1 table: may fail if address above 16TB */
200                         if ( frame > 0xffffffffUL )
201                                 return -ERANGE;
202                         writel ( frame, &v1->frame );
203                 }
204
205         } else {
206
207                 /* 32-bit system */
208                 if ( xen->grant.shift ) {
209                         /* Version 2 table: no possible failure */
210                         writel ( frame, &v2->full_page.frame );
211                 } else {
212                         /* Version 1 table: no possible failure */
213                         writel ( frame, &v1->frame );
214                 }
215         }
216
217         /* Record domain ID and flags */
218         writew ( domid, &hdr->domid );
219         wmb();
220         writew ( ( GTF_permit_access | subflags ), &hdr->flags );
221         wmb();
222
223         return 0;
224 }
225
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 );
231
232 #endif /* _IPXE_XENGRANT_H */