@@ -81,12 +81,13 @@ gnttab_t *pick_granted_entry(grant_ref_t ref, domid_t origin_domid)
8181
8282/**
8383 * @brief Create a new grant table entry in the gnttab of a domain
84- *
84+ *
8585 * @param d The domain containing the grant table
8686 * @param target_domid The domain concerned by this grant
8787 * @param pfn The real frame number of the page to be granted
88+ * @param page_count The number of page to grant
8889 */
89- gnttab_t * new_gnttab_entry (struct domain * d , domid_t target_domid , addr_t pfn )
90+ gnttab_t * new_gnttab_entry (struct domain * d , domid_t target_domid , addr_t pfn , size_t page_count )
9091{
9192 gnttab_t * gnttab ;
9293
@@ -96,6 +97,7 @@ gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn)
9697 gnttab -> origin_domid = d -> avz_shared -> domID ;
9798 gnttab -> target_domid = target_domid ;
9899 gnttab -> pfn = pfn ;
100+ gnttab -> page_count = page_count ;
99101
100102 /* Determine the ref number for this entry */
101103 gnttab -> ref = get_ref_max (& d -> gnttab ) + 1 ;
@@ -142,6 +144,31 @@ addr_t allocate_grant_pfn(struct domain *d)
142144 return 0 ; /* Make gcc happy :-) */
143145}
144146
147+ /**
148+ * @brief Find a free long grant pfn
149+ *
150+ * @param d Domain to search for the free pfn
151+ * @return grant pfn object to be used for mapping the granted pages
152+ */
153+ grant_pfn_t * allocate_long_grant_pfn (struct domain * d )
154+ {
155+ int i ;
156+ addr_t start_pfn = d -> long_grant_start_pfn ;
157+
158+ for (i = 0 ; i < NR_LONG_GRANT_PFN ; i ++ ) {
159+ if (d -> long_grant_pfn [i ].free ) {
160+ d -> long_grant_pfn [i ].free = false;
161+ d -> long_grant_pfn [i ].pfn = start_pfn ;
162+ return & d -> long_grant_pfn [i ];
163+ }
164+
165+ start_pfn += d -> long_grant_pfn [i ].page_count ;
166+ }
167+
168+ BUG ();
169+ return NULL ;
170+ }
171+
145172/**
146173 * @brief Map the grant page associated to vbstore in the IPA domain of the ME
147174 *
@@ -179,14 +206,16 @@ addr_t map_vbstore_pfn(int target_domid, int pfn)
179206
180207/**
181208 * @brief Hypercall entry for grant table related operations.
182- *
209+ *
183210 * @param args gnttab detail structure
184211 */
185212void do_gnttab (gnttab_op_t * args )
186213{
187214 struct domain * d ;
188215 addr_t paddr , grant_paddr ;
216+ size_t page_count ;
189217 gnttab_t * gnttab ;
218+ grant_pfn_t * grant_pfn ;
190219
191220 spin_lock (& gnttab_lock );
192221
@@ -198,8 +227,9 @@ void do_gnttab(gnttab_op_t *args)
198227 /* Create a new entry in the list of gnttab page */
199228
200229 paddr = ipa_to_pa (DOM_TO_MEMSLOT (d -> avz_shared -> domID ), pfn_to_phys (args -> pfn ));
230+ page_count = args -> page_count == 0 ? 1 : args -> page_count ;
201231
202- gnttab = new_gnttab_entry (d , args -> domid , phys_to_pfn (paddr ));
232+ gnttab = new_gnttab_entry (d , args -> domid , phys_to_pfn (paddr ), page_count );
203233
204234 args -> ref = gnttab -> ref ;
205235
@@ -215,13 +245,23 @@ void do_gnttab(gnttab_op_t *args)
215245 gnttab = pick_granted_entry (args -> ref , args -> domid );
216246 BUG_ON (!gnttab );
217247
218- /* Here, we get an IPA address corresponding to the grant page */
219- grant_paddr = pfn_to_phys (allocate_grant_pfn (d ));
248+ page_count = gnttab -> page_count ;
249+ if (page_count == 1 ) {
250+ /* Here, we get an IPA address corresponding to the grant page */
251+ grant_paddr = pfn_to_phys (allocate_grant_pfn (d ));
252+ } else {
253+ grant_pfn = allocate_long_grant_pfn (d );
254+
255+ grant_pfn -> page_count = page_count ;
256+ grant_paddr = pfn_to_phys (grant_pfn -> pfn );
257+ }
220258
221259 /* This pfn will be exported to the domain */
222260 args -> pfn = phys_to_pfn (grant_paddr );
261+ args -> page_count = page_count ;
223262
224- __create_mapping ((addr_t * ) d -> pagetable_vaddr , grant_paddr , pfn_to_phys (gnttab -> pfn ), PAGE_SIZE , true, S2 );
263+ __create_mapping ((addr_t * ) d -> pagetable_vaddr , grant_paddr , pfn_to_phys (gnttab -> pfn ), PAGE_SIZE * page_count ,
264+ true, S2 );
225265
226266 break ;
227267
0 commit comments