iPXE
xengrant.h
Go to the documentation of this file.
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_OR_UBDL );
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,
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 addr Physical address within page
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,
176  struct grant_entry_header *hdr = xengrant_header ( xen, ref );
177  struct grant_entry_v1 *v1 = xengrant_v1 ( hdr );
178  union grant_entry_v2 *v2 = xengrant_v2 ( hdr );
179  unsigned long frame = ( addr / PAGE_SIZE );
180 
181  /* Fail (for test purposes) if applicable */
182  if ( ( XENGRANT_FAIL_RATE > 0 ) &&
183  ( random() % XENGRANT_FAIL_RATE ) == 0 ) {
184  return -EAGAIN;
185  }
186 
187  /* Record frame number. This may fail on a 64-bit system if
188  * we are using v1 grant tables. On a 32-bit system, there is
189  * no way for this code path to fail (with either v1 or v2
190  * grant tables); we allow the compiler to optimise the
191  * failure paths away to save space.
192  */
193  if ( sizeof ( physaddr_t ) == sizeof ( uint64_t ) ) {
194 
195  /* 64-bit system */
196  if ( xen->grant.shift ) {
197  /* Version 2 table: no possible failure */
198  writeq ( frame, &v2->full_page.frame );
199  } else {
200  /* Version 1 table: may fail if address above 16TB */
201  if ( frame > 0xffffffffUL )
202  return -ERANGE;
203  writel ( frame, &v1->frame );
204  }
205 
206  } else {
207 
208  /* 32-bit system */
209  if ( xen->grant.shift ) {
210  /* Version 2 table: no possible failure */
211  writel ( frame, &v2->full_page.frame );
212  } else {
213  /* Version 1 table: no possible failure */
214  writel ( frame, &v1->frame );
215  }
216  }
217 
218  /* Record domain ID and flags */
219  writew ( domid, &hdr->domid );
220  wmb();
221  writew ( ( GTF_permit_access | subflags ), &hdr->flags );
222  wmb();
223 
224  return 0;
225 }
226 
227 extern int xengrant_init ( struct xen_hypervisor *xen );
228 extern int xengrant_alloc ( struct xen_hypervisor *xen, grant_ref_t *refs,
229  unsigned int count );
230 extern void xengrant_free ( struct xen_hypervisor *xen, grant_ref_t *refs,
231  unsigned int count );
232 
233 #endif /* _IPXE_XENGRANT_H */
iPXE I/O API
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
wmb()
uint16_t domid_t
Definition: xen.h:608
void xengrant_free(struct xen_hypervisor *xen, grant_ref_t *refs, unsigned int count)
Free grant references.
Definition: xengrant.c:214
struct golan_inbox_hdr hdr
Message header.
Definition: CIB_PRM.h:28
uint16_t readw(volatile uint16_t *io_addr)
Read 16-bit word from memory-mapped device.
#define GTF_writing
Definition: grant_table.h:171
v1
Definition: xengrant.h:93
unsigned long long uint64_t
Definition: stdint.h:13
static grant_ref_t domid_t unsigned int physaddr_t addr
Definition: xengrant.h:175
#define PAGE_SIZE
Page size.
Definition: io.h:27
uint32_t grant_ref_t
Definition: grant_table.h:99
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
A Xen hypervisor.
Definition: xen.h:51
Xen interface.
#define GTF_reading
Definition: grant_table.h:169
unsigned long frame
Definition: xengrant.h:179
#define XENGRANT_FAIL_RATE
Induced failure rate (for testing)
Definition: xengrant.h:19
static struct gnttab_set_version * version
Definition: xengrant.h:46
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
static __attribute__((always_inline)) int xengrant_query_size(struct xen_hypervisor *xen
Query grant table size.
Definition: xengrant.h:75
void writel(uint32_t data, volatile uint32_t *io_addr)
Write 32-bit dword to memory-mapped device.
struct grant_entry_v1 * table
Grant table entries.
Definition: xen.h:31
static grant_ref_t domid_t unsigned int subflags
Definition: xengrant.h:173
#define __HYPERVISOR_grant_table_op
Definition: xen.h:96
#define ERANGE
Result too large.
Definition: errno.h:639
static const char grant_ref_t unsigned int struct io_buffer grant_ref_t * refs
Definition: netfront.h:93
static grant_ref_t domid_t domid
Definition: xengrant.h:173
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:31
Definition: grant_table.h:117
unsigned int uint32_t
Definition: stdint.h:12
#define EAGAIN
Resource temporarily unavailable.
Definition: errno.h:318
#define GNTTABOP_query_size
Definition: grant_table.h:295
union grant_entry_v2 * v2
Definition: xengrant.h:178
unsigned long physaddr_t
Definition: stdint.h:20
writew(0, &hdr->flags)
unsigned int shift
Entry size shift (for later version tables)
Definition: xen.h:35
struct xen_grant grant
Grant table.
Definition: xen.h:57
uint16_t count
Number of entries.
Definition: ena.h:22
#define DOMID_SELF
Definition: xen.h:567
static struct gnttab_query_size * size
Definition: xengrant.h:30
size_t len
Total grant table length.
Definition: xen.h:33
int xengrant_init(struct xen_hypervisor *xen)
Initialise grant table.
Definition: xengrant.c:70
int xengrant_alloc(struct xen_hypervisor *xen, grant_ref_t *refs, unsigned int count)
Allocate grant references.
Definition: xengrant.c:148
static grant_ref_t ref
Definition: xengrant.h:90
#define GTF_permit_access
Definition: grant_table.h:149
static void xengrant_zero(struct xen_hypervisor *xen, struct grant_entry_header *hdr)
Zero grant table entry.
Definition: xengrant.h:127
void writeq(uint64_t data, volatile uint64_t *io_addr)
Write 64-bit qword to memory-mapped device.
unsigned long int dword
Definition: smc9000.h:40
struct xen_hypervisor * xen
Xen hypervisor.
Definition: xenbus.h:22
uint8_t flags
Flags.
Definition: ena.h:18