diff options
-rw-r--r-- | arch/x86/xen/grant-table.c | 7 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 181 | ||||
-rw-r--r-- | include/xen/grant_table.h | 4 | ||||
-rw-r--r-- | include/xen/interface/grant_table.h | 167 | ||||
-rw-r--r-- | include/xen/interface/xen.h | 2 |
5 files changed, 310 insertions, 51 deletions
diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index 6bbfd7ac5e81..c6ab2e7ca3a6 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c | |||
@@ -64,10 +64,10 @@ static int unmap_pte_fn(pte_t *pte, struct page *pmd_page, | |||
64 | 64 | ||
65 | int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, | 65 | int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, |
66 | unsigned long max_nr_gframes, | 66 | unsigned long max_nr_gframes, |
67 | struct grant_entry **__shared) | 67 | void **__shared) |
68 | { | 68 | { |
69 | int rc; | 69 | int rc; |
70 | struct grant_entry *shared = *__shared; | 70 | void *shared = *__shared; |
71 | 71 | ||
72 | if (shared == NULL) { | 72 | if (shared == NULL) { |
73 | struct vm_struct *area = | 73 | struct vm_struct *area = |
@@ -83,8 +83,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, | |||
83 | return rc; | 83 | return rc; |
84 | } | 84 | } |
85 | 85 | ||
86 | void arch_gnttab_unmap_shared(struct grant_entry *shared, | 86 | void arch_gnttab_unmap_shared(void *shared, unsigned long nr_gframes) |
87 | unsigned long nr_gframes) | ||
88 | { | 87 | { |
89 | apply_to_page_range(&init_mm, (unsigned long)shared, | 88 | apply_to_page_range(&init_mm, (unsigned long)shared, |
90 | PAGE_SIZE * nr_gframes, unmap_pte_fn, NULL); | 89 | PAGE_SIZE * nr_gframes, unmap_pte_fn, NULL); |
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index bf1c094f4ebf..18355a53763f 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -53,7 +53,7 @@ | |||
53 | /* External tools reserve first few grant table entries. */ | 53 | /* External tools reserve first few grant table entries. */ |
54 | #define NR_RESERVED_ENTRIES 8 | 54 | #define NR_RESERVED_ENTRIES 8 |
55 | #define GNTTAB_LIST_END 0xffffffff | 55 | #define GNTTAB_LIST_END 0xffffffff |
56 | #define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(struct grant_entry)) | 56 | #define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(struct grant_entry_v1)) |
57 | 57 | ||
58 | static grant_ref_t **gnttab_list; | 58 | static grant_ref_t **gnttab_list; |
59 | static unsigned int nr_grant_frames; | 59 | static unsigned int nr_grant_frames; |
@@ -64,7 +64,63 @@ static DEFINE_SPINLOCK(gnttab_list_lock); | |||
64 | unsigned long xen_hvm_resume_frames; | 64 | unsigned long xen_hvm_resume_frames; |
65 | EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); | 65 | EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); |
66 | 66 | ||
67 | static struct grant_entry *shared; | 67 | static union { |
68 | struct grant_entry_v1 *v1; | ||
69 | void *addr; | ||
70 | } gnttab_shared; | ||
71 | |||
72 | /*This is a structure of function pointers for grant table*/ | ||
73 | struct gnttab_ops { | ||
74 | /* | ||
75 | * Mapping a list of frames for storing grant entries. First input | ||
76 | * parameter is used to storing grant table address when grant table | ||
77 | * being setup, second parameter is the number of frames to map grant | ||
78 | * table. Returning GNTST_okay means success and negative value means | ||
79 | * failure. | ||
80 | */ | ||
81 | int (*map_frames)(unsigned long *, unsigned int); | ||
82 | /* | ||
83 | * Release a list of frames which are mapped in map_frames for grant | ||
84 | * entry status. | ||
85 | */ | ||
86 | void (*unmap_frames)(void); | ||
87 | /* | ||
88 | * Introducing a valid entry into the grant table, granting the frame | ||
89 | * of this grant entry to domain for accessing, or transfering, or | ||
90 | * transitively accessing. First input parameter is reference of this | ||
91 | * introduced grant entry, second one is domid of granted domain, third | ||
92 | * one is the frame to be granted, and the last one is status of the | ||
93 | * grant entry to be updated. | ||
94 | */ | ||
95 | void (*update_entry)(grant_ref_t, domid_t, unsigned long, unsigned); | ||
96 | /* | ||
97 | * Stop granting a grant entry to domain for accessing. First input | ||
98 | * parameter is reference of a grant entry whose grant access will be | ||
99 | * stopped, second one is not in use now. If the grant entry is | ||
100 | * currently mapped for reading or writing, just return failure(==0) | ||
101 | * directly and don't tear down the grant access. Otherwise, stop grant | ||
102 | * access for this entry and return success(==1). | ||
103 | */ | ||
104 | int (*end_foreign_access_ref)(grant_ref_t, int); | ||
105 | /* | ||
106 | * Stop granting a grant entry to domain for transfer. If tranfer has | ||
107 | * not started, just reclaim the grant entry and return failure(==0). | ||
108 | * Otherwise, wait for the transfer to complete and then return the | ||
109 | * frame. | ||
110 | */ | ||
111 | unsigned long (*end_foreign_transfer_ref)(grant_ref_t); | ||
112 | /* | ||
113 | * Query the status of a grant entry. Input parameter is reference of | ||
114 | * queried grant entry, return value is the status of queried entry. | ||
115 | * Detailed status(writing/reading) can be gotten from the return value | ||
116 | * by bit operations. | ||
117 | */ | ||
118 | int (*query_foreign_access)(grant_ref_t); | ||
119 | }; | ||
120 | |||
121 | static struct gnttab_ops *gnttab_interface; | ||
122 | |||
123 | static int grant_table_version; | ||
68 | 124 | ||
69 | static struct gnttab_free_callback *gnttab_free_callback_list; | 125 | static struct gnttab_free_callback *gnttab_free_callback_list; |
70 | 126 | ||
@@ -142,23 +198,23 @@ static void put_free_entry(grant_ref_t ref) | |||
142 | spin_unlock_irqrestore(&gnttab_list_lock, flags); | 198 | spin_unlock_irqrestore(&gnttab_list_lock, flags); |
143 | } | 199 | } |
144 | 200 | ||
145 | static void update_grant_entry(grant_ref_t ref, domid_t domid, | 201 | /* |
146 | unsigned long frame, unsigned flags) | 202 | * Introducing a valid entry into the grant table: |
203 | * 1. Write ent->domid. | ||
204 | * 2. Write ent->frame: | ||
205 | * GTF_permit_access: Frame to which access is permitted. | ||
206 | * GTF_accept_transfer: Pseudo-phys frame slot being filled by new | ||
207 | * frame, or zero if none. | ||
208 | * 3. Write memory barrier (WMB). | ||
209 | * 4. Write ent->flags, inc. valid type. | ||
210 | */ | ||
211 | static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid, | ||
212 | unsigned long frame, unsigned flags) | ||
147 | { | 213 | { |
148 | /* | 214 | gnttab_shared.v1[ref].domid = domid; |
149 | * Introducing a valid entry into the grant table: | 215 | gnttab_shared.v1[ref].frame = frame; |
150 | * 1. Write ent->domid. | ||
151 | * 2. Write ent->frame: | ||
152 | * GTF_permit_access: Frame to which access is permitted. | ||
153 | * GTF_accept_transfer: Pseudo-phys frame slot being filled by new | ||
154 | * frame, or zero if none. | ||
155 | * 3. Write memory barrier (WMB). | ||
156 | * 4. Write ent->flags, inc. valid type. | ||
157 | */ | ||
158 | shared[ref].frame = frame; | ||
159 | shared[ref].domid = domid; | ||
160 | wmb(); | 216 | wmb(); |
161 | shared[ref].flags = flags; | 217 | gnttab_shared.v1[ref].flags = flags; |
162 | } | 218 | } |
163 | 219 | ||
164 | /* | 220 | /* |
@@ -167,7 +223,7 @@ static void update_grant_entry(grant_ref_t ref, domid_t domid, | |||
167 | void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, | 223 | void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, |
168 | unsigned long frame, int readonly) | 224 | unsigned long frame, int readonly) |
169 | { | 225 | { |
170 | update_grant_entry(ref, domid, frame, | 226 | gnttab_interface->update_entry(ref, domid, frame, |
171 | GTF_permit_access | (readonly ? GTF_readonly : 0)); | 227 | GTF_permit_access | (readonly ? GTF_readonly : 0)); |
172 | } | 228 | } |
173 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref); | 229 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref); |
@@ -187,31 +243,37 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, | |||
187 | } | 243 | } |
188 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); | 244 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); |
189 | 245 | ||
190 | int gnttab_query_foreign_access(grant_ref_t ref) | 246 | static int gnttab_query_foreign_access_v1(grant_ref_t ref) |
191 | { | 247 | { |
192 | u16 nflags; | 248 | return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing); |
193 | 249 | } | |
194 | nflags = shared[ref].flags; | ||
195 | 250 | ||
196 | return nflags & (GTF_reading|GTF_writing); | 251 | int gnttab_query_foreign_access(grant_ref_t ref) |
252 | { | ||
253 | return gnttab_interface->query_foreign_access(ref); | ||
197 | } | 254 | } |
198 | EXPORT_SYMBOL_GPL(gnttab_query_foreign_access); | 255 | EXPORT_SYMBOL_GPL(gnttab_query_foreign_access); |
199 | 256 | ||
200 | int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) | 257 | static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly) |
201 | { | 258 | { |
202 | u16 flags, nflags; | 259 | u16 flags, nflags; |
203 | 260 | ||
204 | nflags = shared[ref].flags; | 261 | nflags = gnttab_shared.v1[ref].flags; |
205 | do { | 262 | do { |
206 | flags = nflags; | 263 | flags = nflags; |
207 | if (flags & (GTF_reading|GTF_writing)) { | 264 | if (flags & (GTF_reading|GTF_writing)) { |
208 | printk(KERN_ALERT "WARNING: g.e. still in use!\n"); | 265 | printk(KERN_ALERT "WARNING: g.e. still in use!\n"); |
209 | return 0; | 266 | return 0; |
210 | } | 267 | } |
211 | } while ((nflags = sync_cmpxchg(&shared[ref].flags, flags, 0)) != flags); | 268 | } while ((nflags = sync_cmpxchg(&gnttab_shared.v1[ref].flags, flags, 0)) != flags); |
212 | 269 | ||
213 | return 1; | 270 | return 1; |
214 | } | 271 | } |
272 | |||
273 | int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) | ||
274 | { | ||
275 | return gnttab_interface->end_foreign_access_ref(ref, readonly); | ||
276 | } | ||
215 | EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref); | 277 | EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref); |
216 | 278 | ||
217 | void gnttab_end_foreign_access(grant_ref_t ref, int readonly, | 279 | void gnttab_end_foreign_access(grant_ref_t ref, int readonly, |
@@ -246,11 +308,11 @@ EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer); | |||
246 | void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, | 308 | void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, |
247 | unsigned long pfn) | 309 | unsigned long pfn) |
248 | { | 310 | { |
249 | update_grant_entry(ref, domid, pfn, GTF_accept_transfer); | 311 | gnttab_interface->update_entry(ref, domid, pfn, GTF_accept_transfer); |
250 | } | 312 | } |
251 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref); | 313 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref); |
252 | 314 | ||
253 | unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) | 315 | static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref) |
254 | { | 316 | { |
255 | unsigned long frame; | 317 | unsigned long frame; |
256 | u16 flags; | 318 | u16 flags; |
@@ -259,24 +321,29 @@ unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) | |||
259 | * If a transfer is not even yet started, try to reclaim the grant | 321 | * If a transfer is not even yet started, try to reclaim the grant |
260 | * reference and return failure (== 0). | 322 | * reference and return failure (== 0). |
261 | */ | 323 | */ |
262 | while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { | 324 | while (!((flags = gnttab_shared.v1[ref].flags) & GTF_transfer_committed)) { |
263 | if (sync_cmpxchg(&shared[ref].flags, flags, 0) == flags) | 325 | if (sync_cmpxchg(&gnttab_shared.v1[ref].flags, flags, 0) == flags) |
264 | return 0; | 326 | return 0; |
265 | cpu_relax(); | 327 | cpu_relax(); |
266 | } | 328 | } |
267 | 329 | ||
268 | /* If a transfer is in progress then wait until it is completed. */ | 330 | /* If a transfer is in progress then wait until it is completed. */ |
269 | while (!(flags & GTF_transfer_completed)) { | 331 | while (!(flags & GTF_transfer_completed)) { |
270 | flags = shared[ref].flags; | 332 | flags = gnttab_shared.v1[ref].flags; |
271 | cpu_relax(); | 333 | cpu_relax(); |
272 | } | 334 | } |
273 | 335 | ||
274 | rmb(); /* Read the frame number /after/ reading completion status. */ | 336 | rmb(); /* Read the frame number /after/ reading completion status. */ |
275 | frame = shared[ref].frame; | 337 | frame = gnttab_shared.v1[ref].frame; |
276 | BUG_ON(frame == 0); | 338 | BUG_ON(frame == 0); |
277 | 339 | ||
278 | return frame; | 340 | return frame; |
279 | } | 341 | } |
342 | |||
343 | unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) | ||
344 | { | ||
345 | return gnttab_interface->end_foreign_transfer_ref(ref); | ||
346 | } | ||
280 | EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref); | 347 | EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref); |
281 | 348 | ||
282 | unsigned long gnttab_end_foreign_transfer(grant_ref_t ref) | 349 | unsigned long gnttab_end_foreign_transfer(grant_ref_t ref) |
@@ -520,6 +587,23 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
520 | } | 587 | } |
521 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | 588 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); |
522 | 589 | ||
590 | static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes) | ||
591 | { | ||
592 | int rc; | ||
593 | |||
594 | rc = arch_gnttab_map_shared(frames, nr_gframes, | ||
595 | gnttab_max_grant_frames(), | ||
596 | &gnttab_shared.addr); | ||
597 | BUG_ON(rc); | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static void gnttab_unmap_frames_v1(void) | ||
603 | { | ||
604 | arch_gnttab_unmap_shared(gnttab_shared.addr, nr_grant_frames); | ||
605 | } | ||
606 | |||
523 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | 607 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) |
524 | { | 608 | { |
525 | struct gnttab_setup_table setup; | 609 | struct gnttab_setup_table setup; |
@@ -567,19 +651,35 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
567 | 651 | ||
568 | BUG_ON(rc || setup.status); | 652 | BUG_ON(rc || setup.status); |
569 | 653 | ||
570 | rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(), | 654 | rc = gnttab_interface->map_frames(frames, nr_gframes); |
571 | &shared); | ||
572 | BUG_ON(rc); | ||
573 | 655 | ||
574 | kfree(frames); | 656 | kfree(frames); |
575 | 657 | ||
576 | return 0; | 658 | return rc; |
659 | } | ||
660 | |||
661 | static struct gnttab_ops gnttab_v1_ops = { | ||
662 | .map_frames = gnttab_map_frames_v1, | ||
663 | .unmap_frames = gnttab_unmap_frames_v1, | ||
664 | .update_entry = gnttab_update_entry_v1, | ||
665 | .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1, | ||
666 | .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1, | ||
667 | .query_foreign_access = gnttab_query_foreign_access_v1, | ||
668 | }; | ||
669 | |||
670 | static void gnttab_request_version(void) | ||
671 | { | ||
672 | grant_table_version = 1; | ||
673 | gnttab_interface = &gnttab_v1_ops; | ||
674 | printk(KERN_INFO "Grant tables using version %d layout.\n", | ||
675 | grant_table_version); | ||
577 | } | 676 | } |
578 | 677 | ||
579 | int gnttab_resume(void) | 678 | int gnttab_resume(void) |
580 | { | 679 | { |
581 | unsigned int max_nr_gframes; | 680 | unsigned int max_nr_gframes; |
582 | 681 | ||
682 | gnttab_request_version(); | ||
583 | max_nr_gframes = gnttab_max_grant_frames(); | 683 | max_nr_gframes = gnttab_max_grant_frames(); |
584 | if (max_nr_gframes < nr_grant_frames) | 684 | if (max_nr_gframes < nr_grant_frames) |
585 | return -ENOSYS; | 685 | return -ENOSYS; |
@@ -587,9 +687,10 @@ int gnttab_resume(void) | |||
587 | if (xen_pv_domain()) | 687 | if (xen_pv_domain()) |
588 | return gnttab_map(0, nr_grant_frames - 1); | 688 | return gnttab_map(0, nr_grant_frames - 1); |
589 | 689 | ||
590 | if (!shared) { | 690 | if (gnttab_shared.addr == NULL) { |
591 | shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes); | 691 | gnttab_shared.addr = ioremap(xen_hvm_resume_frames, |
592 | if (shared == NULL) { | 692 | PAGE_SIZE * max_nr_gframes); |
693 | if (gnttab_shared.addr == NULL) { | ||
593 | printk(KERN_WARNING | 694 | printk(KERN_WARNING |
594 | "Failed to ioremap gnttab share frames!"); | 695 | "Failed to ioremap gnttab share frames!"); |
595 | return -ENOMEM; | 696 | return -ENOMEM; |
@@ -603,7 +704,7 @@ int gnttab_resume(void) | |||
603 | 704 | ||
604 | int gnttab_suspend(void) | 705 | int gnttab_suspend(void) |
605 | { | 706 | { |
606 | arch_gnttab_unmap_shared(shared, nr_grant_frames); | 707 | gnttab_interface->unmap_frames(); |
607 | return 0; | 708 | return 0; |
608 | } | 709 | } |
609 | 710 | ||
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 11e2dfce42f8..c7a40f8d455a 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h | |||
@@ -145,8 +145,8 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr, | |||
145 | 145 | ||
146 | int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, | 146 | int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, |
147 | unsigned long max_nr_gframes, | 147 | unsigned long max_nr_gframes, |
148 | struct grant_entry **__shared); | 148 | void **__shared); |
149 | void arch_gnttab_unmap_shared(struct grant_entry *shared, | 149 | void arch_gnttab_unmap_shared(void *shared, |
150 | unsigned long nr_gframes); | 150 | unsigned long nr_gframes); |
151 | 151 | ||
152 | extern unsigned long xen_hvm_resume_frames; | 152 | extern unsigned long xen_hvm_resume_frames; |
diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h index 39e571796e32..a17d84433e6a 100644 --- a/include/xen/interface/grant_table.h +++ b/include/xen/interface/grant_table.h | |||
@@ -85,12 +85,22 @@ | |||
85 | */ | 85 | */ |
86 | 86 | ||
87 | /* | 87 | /* |
88 | * Reference to a grant entry in a specified domain's grant table. | ||
89 | */ | ||
90 | typedef uint32_t grant_ref_t; | ||
91 | |||
92 | /* | ||
88 | * A grant table comprises a packed array of grant entries in one or more | 93 | * A grant table comprises a packed array of grant entries in one or more |
89 | * page frames shared between Xen and a guest. | 94 | * page frames shared between Xen and a guest. |
90 | * [XEN]: This field is written by Xen and read by the sharing guest. | 95 | * [XEN]: This field is written by Xen and read by the sharing guest. |
91 | * [GST]: This field is written by the guest and read by Xen. | 96 | * [GST]: This field is written by the guest and read by Xen. |
92 | */ | 97 | */ |
93 | struct grant_entry { | 98 | |
99 | /* | ||
100 | * Version 1 of the grant table entry structure is maintained purely | ||
101 | * for backwards compatibility. New guests should use version 2. | ||
102 | */ | ||
103 | struct grant_entry_v1 { | ||
94 | /* GTF_xxx: various type and flag information. [XEN,GST] */ | 104 | /* GTF_xxx: various type and flag information. [XEN,GST] */ |
95 | uint16_t flags; | 105 | uint16_t flags; |
96 | /* The domain being granted foreign privileges. [GST] */ | 106 | /* The domain being granted foreign privileges. [GST] */ |
@@ -108,10 +118,13 @@ struct grant_entry { | |||
108 | * GTF_permit_access: Allow @domid to map/access @frame. | 118 | * GTF_permit_access: Allow @domid to map/access @frame. |
109 | * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame | 119 | * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame |
110 | * to this guest. Xen writes the page number to @frame. | 120 | * to this guest. Xen writes the page number to @frame. |
121 | * GTF_transitive: Allow @domid to transitively access a subrange of | ||
122 | * @trans_grant in @trans_domid. No mappings are allowed. | ||
111 | */ | 123 | */ |
112 | #define GTF_invalid (0U<<0) | 124 | #define GTF_invalid (0U<<0) |
113 | #define GTF_permit_access (1U<<0) | 125 | #define GTF_permit_access (1U<<0) |
114 | #define GTF_accept_transfer (2U<<0) | 126 | #define GTF_accept_transfer (2U<<0) |
127 | #define GTF_transitive (3U<<0) | ||
115 | #define GTF_type_mask (3U<<0) | 128 | #define GTF_type_mask (3U<<0) |
116 | 129 | ||
117 | /* | 130 | /* |
@@ -119,6 +132,9 @@ struct grant_entry { | |||
119 | * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST] | 132 | * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST] |
120 | * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN] | 133 | * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN] |
121 | * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN] | 134 | * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN] |
135 | * GTF_sub_page: Grant access to only a subrange of the page. @domid | ||
136 | * will only be allowed to copy from the grant, and not | ||
137 | * map it. [GST] | ||
122 | */ | 138 | */ |
123 | #define _GTF_readonly (2) | 139 | #define _GTF_readonly (2) |
124 | #define GTF_readonly (1U<<_GTF_readonly) | 140 | #define GTF_readonly (1U<<_GTF_readonly) |
@@ -126,6 +142,8 @@ struct grant_entry { | |||
126 | #define GTF_reading (1U<<_GTF_reading) | 142 | #define GTF_reading (1U<<_GTF_reading) |
127 | #define _GTF_writing (4) | 143 | #define _GTF_writing (4) |
128 | #define GTF_writing (1U<<_GTF_writing) | 144 | #define GTF_writing (1U<<_GTF_writing) |
145 | #define _GTF_sub_page (8) | ||
146 | #define GTF_sub_page (1U<<_GTF_sub_page) | ||
129 | 147 | ||
130 | /* | 148 | /* |
131 | * Subflags for GTF_accept_transfer: | 149 | * Subflags for GTF_accept_transfer: |
@@ -142,15 +160,81 @@ struct grant_entry { | |||
142 | #define _GTF_transfer_completed (3) | 160 | #define _GTF_transfer_completed (3) |
143 | #define GTF_transfer_completed (1U<<_GTF_transfer_completed) | 161 | #define GTF_transfer_completed (1U<<_GTF_transfer_completed) |
144 | 162 | ||
163 | /* | ||
164 | * Version 2 grant table entries. These fulfil the same role as | ||
165 | * version 1 entries, but can represent more complicated operations. | ||
166 | * Any given domain will have either a version 1 or a version 2 table, | ||
167 | * and every entry in the table will be the same version. | ||
168 | * | ||
169 | * The interface by which domains use grant references does not depend | ||
170 | * on the grant table version in use by the other domain. | ||
171 | */ | ||
145 | 172 | ||
146 | /*********************************** | 173 | /* |
147 | * GRANT TABLE QUERIES AND USES | 174 | * Version 1 and version 2 grant entries share a common prefix. The |
175 | * fields of the prefix are documented as part of struct | ||
176 | * grant_entry_v1. | ||
148 | */ | 177 | */ |
178 | struct grant_entry_header { | ||
179 | uint16_t flags; | ||
180 | domid_t domid; | ||
181 | }; | ||
149 | 182 | ||
150 | /* | 183 | /* |
151 | * Reference to a grant entry in a specified domain's grant table. | 184 | * Version 2 of the grant entry structure, here is an union because three |
185 | * different types are suppotted: full_page, sub_page and transitive. | ||
186 | */ | ||
187 | union grant_entry_v2 { | ||
188 | struct grant_entry_header hdr; | ||
189 | |||
190 | /* | ||
191 | * This member is used for V1-style full page grants, where either: | ||
192 | * | ||
193 | * -- hdr.type is GTF_accept_transfer, or | ||
194 | * -- hdr.type is GTF_permit_access and GTF_sub_page is not set. | ||
195 | * | ||
196 | * In that case, the frame field has the same semantics as the | ||
197 | * field of the same name in the V1 entry structure. | ||
198 | */ | ||
199 | struct { | ||
200 | struct grant_entry_header hdr; | ||
201 | uint32_t pad0; | ||
202 | uint64_t frame; | ||
203 | } full_page; | ||
204 | |||
205 | /* | ||
206 | * If the grant type is GTF_grant_access and GTF_sub_page is set, | ||
207 | * @domid is allowed to access bytes [@page_off,@page_off+@length) | ||
208 | * in frame @frame. | ||
209 | */ | ||
210 | struct { | ||
211 | struct grant_entry_header hdr; | ||
212 | uint16_t page_off; | ||
213 | uint16_t length; | ||
214 | uint64_t frame; | ||
215 | } sub_page; | ||
216 | |||
217 | /* | ||
218 | * If the grant is GTF_transitive, @domid is allowed to use the | ||
219 | * grant @gref in domain @trans_domid, as if it was the local | ||
220 | * domain. Obviously, the transitive access must be compatible | ||
221 | * with the original grant. | ||
222 | */ | ||
223 | struct { | ||
224 | struct grant_entry_header hdr; | ||
225 | domid_t trans_domid; | ||
226 | uint16_t pad0; | ||
227 | grant_ref_t gref; | ||
228 | } transitive; | ||
229 | |||
230 | uint32_t __spacer[4]; /* Pad to a power of two */ | ||
231 | }; | ||
232 | |||
233 | typedef uint16_t grant_status_t; | ||
234 | |||
235 | /*********************************** | ||
236 | * GRANT TABLE QUERIES AND USES | ||
152 | */ | 237 | */ |
153 | typedef uint32_t grant_ref_t; | ||
154 | 238 | ||
155 | /* | 239 | /* |
156 | * Handle to track a mapping created via a grant reference. | 240 | * Handle to track a mapping created via a grant reference. |
@@ -322,6 +406,79 @@ struct gnttab_query_size { | |||
322 | DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size); | 406 | DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size); |
323 | 407 | ||
324 | /* | 408 | /* |
409 | * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings | ||
410 | * tracked by <handle> but atomically replace the page table entry with one | ||
411 | * pointing to the machine address under <new_addr>. <new_addr> will be | ||
412 | * redirected to the null entry. | ||
413 | * NOTES: | ||
414 | * 1. The call may fail in an undefined manner if either mapping is not | ||
415 | * tracked by <handle>. | ||
416 | * 2. After executing a batch of unmaps, it is guaranteed that no stale | ||
417 | * mappings will remain in the device or host TLBs. | ||
418 | */ | ||
419 | #define GNTTABOP_unmap_and_replace 7 | ||
420 | struct gnttab_unmap_and_replace { | ||
421 | /* IN parameters. */ | ||
422 | uint64_t host_addr; | ||
423 | uint64_t new_addr; | ||
424 | grant_handle_t handle; | ||
425 | /* OUT parameters. */ | ||
426 | int16_t status; /* GNTST_* */ | ||
427 | }; | ||
428 | DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_and_replace); | ||
429 | |||
430 | /* | ||
431 | * GNTTABOP_set_version: Request a particular version of the grant | ||
432 | * table shared table structure. This operation can only be performed | ||
433 | * once in any given domain. It must be performed before any grants | ||
434 | * are activated; otherwise, the domain will be stuck with version 1. | ||
435 | * The only defined versions are 1 and 2. | ||
436 | */ | ||
437 | #define GNTTABOP_set_version 8 | ||
438 | struct gnttab_set_version { | ||
439 | /* IN parameters */ | ||
440 | uint32_t version; | ||
441 | }; | ||
442 | DEFINE_GUEST_HANDLE_STRUCT(gnttab_set_version); | ||
443 | |||
444 | /* | ||
445 | * GNTTABOP_get_status_frames: Get the list of frames used to store grant | ||
446 | * status for <dom>. In grant format version 2, the status is separated | ||
447 | * from the other shared grant fields to allow more efficient synchronization | ||
448 | * using barriers instead of atomic cmpexch operations. | ||
449 | * <nr_frames> specify the size of vector <frame_list>. | ||
450 | * The frame addresses are returned in the <frame_list>. | ||
451 | * Only <nr_frames> addresses are returned, even if the table is larger. | ||
452 | * NOTES: | ||
453 | * 1. <dom> may be specified as DOMID_SELF. | ||
454 | * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF. | ||
455 | */ | ||
456 | #define GNTTABOP_get_status_frames 9 | ||
457 | struct gnttab_get_status_frames { | ||
458 | /* IN parameters. */ | ||
459 | uint32_t nr_frames; | ||
460 | domid_t dom; | ||
461 | /* OUT parameters. */ | ||
462 | int16_t status; /* GNTST_* */ | ||
463 | GUEST_HANDLE(uint64_t) frame_list; | ||
464 | }; | ||
465 | DEFINE_GUEST_HANDLE_STRUCT(gnttab_get_status_frames); | ||
466 | |||
467 | /* | ||
468 | * GNTTABOP_get_version: Get the grant table version which is in | ||
469 | * effect for domain <dom>. | ||
470 | */ | ||
471 | #define GNTTABOP_get_version 10 | ||
472 | struct gnttab_get_version { | ||
473 | /* IN parameters */ | ||
474 | domid_t dom; | ||
475 | uint16_t pad; | ||
476 | /* OUT parameters */ | ||
477 | uint32_t version; | ||
478 | }; | ||
479 | DEFINE_GUEST_HANDLE_STRUCT(gnttab_get_version); | ||
480 | |||
481 | /* | ||
325 | * Bitfield values for update_pin_status.flags. | 482 | * Bitfield values for update_pin_status.flags. |
326 | */ | 483 | */ |
327 | /* Map the grant entry for access by I/O devices. */ | 484 | /* Map the grant entry for access by I/O devices. */ |
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 6a6e91449347..a890804945e3 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h | |||
@@ -523,6 +523,8 @@ struct tmem_op { | |||
523 | } u; | 523 | } u; |
524 | }; | 524 | }; |
525 | 525 | ||
526 | DEFINE_GUEST_HANDLE(u64); | ||
527 | |||
526 | #else /* __ASSEMBLY__ */ | 528 | #else /* __ASSEMBLY__ */ |
527 | 529 | ||
528 | /* In assembly code we cannot use C numeric constant suffixes. */ | 530 | /* In assembly code we cannot use C numeric constant suffixes. */ |