34 #include <linux/module.h>
35 #include <linux/sched.h>
37 #include <linux/slab.h>
50 #include <asm/xen/hypercall.h>
51 #include <asm/xen/interface.h>
53 #include <asm/pgtable.h>
54 #include <asm/sync_bitops.h>
57 #define NR_RESERVED_ENTRIES 8
58 #define GNTTAB_LIST_END 0xffffffff
59 #define GREFS_PER_GRANT_FRAME \
60 (grant_table_version == 1 ? \
61 (PAGE_SIZE / sizeof(struct grant_entry_v1)) : \
62 (PAGE_SIZE / sizeof(union grant_entry_v2)))
65 static unsigned int nr_grant_frames;
66 static unsigned int boot_max_nr_grant_frames;
67 static int gnttab_free_count;
136 unsigned page_off,
unsigned length);
156 static int grant_table_version;
160 static int gnttab_expand(
unsigned int req_entries);
162 #define RPP (PAGE_SIZE / sizeof(grant_ref_t))
163 #define SPP (PAGE_SIZE / sizeof(grant_status_t))
170 #define gnttab_entry(entry) (*__gnttab_entry(entry))
172 static int get_free_entries(
unsigned count)
180 if ((gnttab_free_count < count) &&
181 ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
182 spin_unlock_irqrestore(&gnttab_list_lock, flags);
186 ref = head = gnttab_free_head;
187 gnttab_free_count -=
count;
193 spin_unlock_irqrestore(&gnttab_list_lock, flags);
198 static void do_free_callbacks(
void)
202 callback = gnttab_free_callback_list;
203 gnttab_free_callback_list =
NULL;
205 while (callback !=
NULL) {
206 next = callback->
next;
207 if (gnttab_free_count >= callback->
count) {
209 callback->
fn(callback->
arg);
211 callback->
next = gnttab_free_callback_list;
212 gnttab_free_callback_list =
callback;
218 static inline void check_free_callbacks(
void)
220 if (
unlikely(gnttab_free_callback_list))
229 gnttab_free_head = ref;
231 check_free_callbacks();
232 spin_unlock_irqrestore(&gnttab_list_lock, flags);
249 gnttab_shared.v1[ref].domid =
domid;
250 gnttab_shared.v1[ref].frame =
frame;
252 gnttab_shared.v1[ref].flags =
flags;
258 gnttab_shared.v2[ref].hdr.domid =
domid;
259 gnttab_shared.v2[ref].full_page.frame =
frame;
280 ref = get_free_entries(1);
292 unsigned page_off,
unsigned length)
294 gnttab_shared.v2[ref].sub_page.frame =
frame;
295 gnttab_shared.v2[ref].sub_page.page_off = page_off;
296 gnttab_shared.v2[ref].sub_page.length =
length;
297 gnttab_shared.v2[ref].hdr.domid =
domid;
299 gnttab_shared.v2[ref].hdr.flags =
323 int flags,
unsigned page_off,
328 ref = get_free_entries(1);
353 gnttab_shared.v2[ref].transitive.trans_domid = trans_domid;
354 gnttab_shared.v2[ref].transitive.gref = trans_gref;
355 gnttab_shared.v2[ref].hdr.domid =
domid;
357 gnttab_shared.v2[ref].hdr.flags =
385 ref = get_free_entries(1);
390 trans_domid, trans_gref);
406 static int gnttab_query_foreign_access_v1(
grant_ref_t ref)
411 static int gnttab_query_foreign_access_v2(
grant_ref_t ref)
427 pflags = &gnttab_shared.v1[ref].flags;
433 }
while ((nflags =
sync_cmpxchg(pflags, flags, 0)) != flags);
438 static int gnttab_end_foreign_access_ref_v2(
grant_ref_t ref,
int readonly)
440 gnttab_shared.v2[ref].hdr.flags = 0;
461 static inline int _gnttab_end_foreign_access_ref(
grant_ref_t ref,
int readonly)
468 if (_gnttab_end_foreign_access_ref(ref, readonly))
470 pr_warn(
"WARNING: g.e. %#x still in use!\n", ref);
483 static void gnttab_handle_deferred(
unsigned long);
484 static DEFINE_TIMER(deferred_timer, gnttab_handle_deferred, 0, 0);
486 static void gnttab_handle_deferred(
unsigned long unused)
488 unsigned int nr = 10;
501 spin_unlock_irqrestore(&gnttab_list_lock, flags);
502 if (_gnttab_end_foreign_access_ref(entry->
ref, entry->
ro)) {
503 put_free_entry(entry->
ref);
505 pr_debug(
"freeing g.e. %#x (pfn %#lx)\n",
514 pr_info(
"g.e. %#x still pending\n",
522 else if (list_empty(&deferred_list))
525 if (!list_empty(&deferred_list) && !timer_pending(&deferred_timer)) {
529 spin_unlock_irqrestore(&gnttab_list_lock, flags);
532 static void gnttab_add_deferred(
grant_ref_t ref,
bool readonly,
547 if (!timer_pending(&deferred_timer)) {
551 spin_unlock_irqrestore(&gnttab_list_lock, flags);
554 printk(
"%s g.e. %#x (pfn %#lx)\n",
566 gnttab_add_deferred(ref, readonly,
575 ref = get_free_entries(1);
591 static unsigned long gnttab_end_foreign_transfer_ref_v1(
grant_ref_t ref)
597 pflags = &gnttab_shared.v1[
ref].flags;
616 frame = gnttab_shared.v1[
ref].frame;
622 static unsigned long gnttab_end_foreign_transfer_ref_v2(
grant_ref_t ref)
628 pflags = &gnttab_shared.v2[
ref].hdr.flags;
634 while (!((flags = *pflags) & GTF_transfer_committed)) {
647 frame = gnttab_shared.v2[
ref].full_page.frame;
687 gnttab_free_head =
head;
688 gnttab_free_count +=
count;
689 check_free_callbacks();
690 spin_unlock_irqrestore(&gnttab_list_lock, flags);
696 int h = get_free_entries(count);
741 callback->
next = gnttab_free_callback_list;
742 gnttab_free_callback_list =
callback;
743 check_free_callbacks();
745 spin_unlock_irqrestore(&gnttab_list_lock, flags);
755 for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->
next) {
756 if (*pcb == callback) {
757 *pcb = callback->
next;
761 spin_unlock_irqrestore(&gnttab_list_lock, flags);
765 static int grow_gnttab_list(
unsigned int more_frames)
767 unsigned int new_nr_grant_frames, extra_entries,
i;
768 unsigned int nr_glist_frames, new_nr_glist_frames;
770 new_nr_grant_frames = nr_grant_frames + more_frames;
773 nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME +
RPP - 1) /
RPP;
774 new_nr_glist_frames =
775 (new_nr_grant_frames * GREFS_PER_GRANT_FRAME +
RPP - 1) /
RPP;
776 for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
783 for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
784 i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
788 gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
789 gnttab_free_count += extra_entries;
791 nr_grant_frames = new_nr_grant_frames;
793 check_free_callbacks();
798 for ( ; i >= nr_glist_frames; i--)
799 free_page((
unsigned long) gnttab_list[i]);
803 static unsigned int __max_nr_grant_frames(
void)
814 return query.max_nr_frames;
819 unsigned int xen_max = __max_nr_grant_frames();
821 if (xen_max > boot_max_nr_grant_frames)
822 return boot_max_nr_grant_frames;
828 #define MAX_DELAY 256
853 for (op = batch; op < batch +
count; op++)
866 for (op = batch; op < batch +
count; op++)
887 for (i = 0; i <
count; i++)
890 &map_ops[i].
status, __func__);
900 for (i = 0; i <
count; i++) {
902 if (map_ops[i].status)
910 mfn =
PFN_DOWN(map_ops[i].dev_bus_addr);
913 &kmap_ops[i] :
NULL);
944 for (i = 0; i <
count; i++) {
946 &kmap_ops[i] :
NULL);
958 static unsigned nr_status_frames(
unsigned nr_grant_frames)
960 return (nr_grant_frames * GREFS_PER_GRANT_FRAME +
SPP - 1) /
SPP;
963 static int gnttab_map_frames_v1(
xen_pfn_t *frames,
unsigned int nr_gframes)
969 &gnttab_shared.addr);
975 static void gnttab_unmap_frames_v1(
void)
980 static int gnttab_map_frames_v2(
xen_pfn_t *frames,
unsigned int nr_gframes)
983 unsigned int nr_sframes;
987 nr_sframes = nr_status_frames(nr_gframes);
997 getframes.nr_frames = nr_sframes;
1007 BUG_ON(rc || getframes.status);
1017 &gnttab_shared.addr);
1023 static void gnttab_unmap_frames_v2(
void)
1029 static int gnttab_map(
unsigned int start_idx,
unsigned int end_idx)
1033 unsigned int nr_gframes = end_idx + 1;
1038 unsigned int i = end_idx;
1052 "grant table add_to_physmap failed, err=%d\n", rc);
1055 }
while (i-- > start_idx);
1068 setup.nr_frames = nr_gframes;
1079 rc = gnttab_interface->
map_frames(frames, nr_gframes);
1087 .map_frames = gnttab_map_frames_v1,
1088 .unmap_frames = gnttab_unmap_frames_v1,
1089 .update_entry = gnttab_update_entry_v1,
1090 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
1091 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
1092 .query_foreign_access = gnttab_query_foreign_access_v1,
1096 .map_frames = gnttab_map_frames_v2,
1097 .unmap_frames = gnttab_unmap_frames_v2,
1098 .update_entry = gnttab_update_entry_v2,
1099 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2,
1100 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2,
1101 .query_foreign_access = gnttab_query_foreign_access_v2,
1102 .update_subpage_entry = gnttab_update_subpage_entry_v2,
1103 .update_trans_entry = gnttab_update_trans_entry_v2,
1106 static void gnttab_request_version(
void)
1116 if (rc == 0 && gsv.version == 2) {
1117 grant_table_version = 2;
1118 gnttab_interface = &gnttab_v2_ops;
1119 }
else if (grant_table_version == 2) {
1127 panic(
"we need grant tables version 2, but only version 1 is available");
1129 grant_table_version = 1;
1130 gnttab_interface = &gnttab_v1_ops;
1133 grant_table_version);
1138 unsigned int max_nr_gframes;
1140 gnttab_request_version();
1142 if (max_nr_gframes < nr_grant_frames)
1146 return gnttab_map(0, nr_grant_frames - 1);
1148 if (gnttab_shared.addr ==
NULL) {
1151 if (gnttab_shared.addr ==
NULL) {
1153 "Failed to ioremap gnttab share frames!");
1158 gnttab_map(0, nr_grant_frames - 1);
1169 static int gnttab_expand(
unsigned int req_entries)
1174 cur = nr_grant_frames;
1175 extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
1180 rc = gnttab_map(cur, cur + extra - 1);
1182 rc = grow_gnttab_list(extra);
1190 unsigned int max_nr_glist_frames, nr_glist_frames;
1191 unsigned int nr_init_grefs;
1194 nr_grant_frames = 1;
1195 boot_max_nr_grant_frames = __max_nr_grant_frames();
1200 max_nr_glist_frames = (boot_max_nr_grant_frames *
1201 GREFS_PER_GRANT_FRAME /
RPP);
1205 if (gnttab_list ==
NULL)
1208 nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME +
RPP - 1) /
RPP;
1209 for (i = 0; i < nr_glist_frames; i++) {
1211 if (gnttab_list[i] ==
NULL) {
1231 printk(
"Grant table initialized\n");
1235 for (i--; i >= 0; i--)
1236 free_page((
unsigned long)gnttab_list[i]);
1242 static int __devinit __gnttab_init(
void)