direct-io.hg

view extras/mini-os/gnttab.c @ 10734:9b7e1ea4c4d2

[HVM] Sync p2m table across all vcpus on x86_32p xen.
We found VGA acceleration can not work on SMP VMX guests on x86_32p
xen, this is caused by the way we construct p2m table today: only the 1st
l2 page table slot that maps p2m table pages is copied to none-vcpu0 vcpu
monitor page table when VMX is created. But VGA acceleration will
create some p2m table entries beyond the 1st l2 page table slot after HVM is
created, so only vcpu0 can get these p2m entries, and other vcpu can
not do VGA acceleration.

Signed-off-by: Xin Li <xin.b.li@intel.com>
author kfraser@localhost.localdomain
date Wed Jul 26 11:34:12 2006 +0100 (2006-07-26)
parents bbea54da02b5
children 4a669bd50657
line source
1 /*
2 ****************************************************************************
3 * (C) 2006 - Cambridge University
4 ****************************************************************************
5 *
6 * File: gnttab.c
7 * Author: Steven Smith (sos22@cam.ac.uk)
8 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
9 *
10 * Date: July 2006
11 *
12 * Environment: Xen Minimal OS
13 * Description: Simple grant tables implementation. About as stupid as it's
14 * possible to be and still work.
15 *
16 ****************************************************************************
17 */
18 #include <os.h>
19 #include <mm.h>
20 #include <gnttab.h>
22 #define NR_RESERVED_ENTRIES 8
24 #define NR_GRANT_FRAMES 4
25 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
26 #define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
28 static grant_entry_t *gnttab_table;
29 static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
30 static grant_ref_t gnttab_free_head;
32 static grant_ref_t
33 get_free_entries(int count)
34 {
35 grant_ref_t ref;
36 grant_ref_t head;
38 ref = head = gnttab_free_head;
39 while (count-- > 1)
40 head = gnttab_list[head];
41 gnttab_free_head = gnttab_list[head];
42 gnttab_list[head] = GNTTAB_LIST_END;
43 return ref;
44 }
46 static void
47 put_free_entry(grant_ref_t gref)
48 {
49 gnttab_list[gref] = gnttab_free_head;
50 gnttab_free_head = gref;
51 }
53 grant_ref_t
54 gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
55 {
56 grant_ref_t ref;
58 ref = get_free_entries(1);
59 gnttab_table[ref].frame = frame;
60 gnttab_table[ref].domid = domid;
61 wmb();
62 readonly *= GTF_readonly;
63 gnttab_table[ref].flags = GTF_permit_access | readonly;
65 return ref;
66 }
68 grant_ref_t
69 gnttab_grant_transfer(domid_t domid, unsigned long pfn)
70 {
71 grant_ref_t ref;
73 ref = get_free_entries(1);
74 gnttab_table[ref].frame = pfn;
75 gnttab_table[ref].domid = domid;
76 wmb();
77 gnttab_table[ref].flags = GTF_accept_transfer;
79 return ref;
80 }
82 int
83 gnttab_end_access(grant_ref_t ref)
84 {
85 u16 flags, nflags;
87 nflags = gnttab_table[ref].flags;
88 do {
89 if ((flags = nflags) & (GTF_reading|GTF_writing)) {
90 printk("WARNING: g.e. still in use!\n");
91 return 0;
92 }
93 } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
94 flags);
96 put_free_entry(ref);
97 return 1;
98 }
100 unsigned long
101 gnttab_end_transfer(grant_ref_t ref)
102 {
103 unsigned long frame;
104 u16 flags;
106 while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
107 if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
108 printk("Release unused transfer grant.\n");
109 put_free_entry(ref);
110 return 0;
111 }
112 }
114 /* If a transfer is in progress then wait until it is completed. */
115 while (!(flags & GTF_transfer_completed)) {
116 flags = gnttab_table[ref].flags;
117 }
119 /* Read the frame number /after/ reading completion status. */
120 rmb();
121 frame = gnttab_table[ref].frame;
123 put_free_entry(ref);
125 return frame;
126 }
128 grant_ref_t
129 gnttab_alloc_and_grant(void **map)
130 {
131 unsigned long mfn;
132 grant_ref_t gref;
134 *map = (void *)alloc_page();
135 mfn = virt_to_mfn(*map);
136 gref = gnttab_grant_access(0, mfn, 0);
137 return gref;
138 }
140 void
141 init_gnttab(void)
142 {
143 struct gnttab_setup_table setup;
144 unsigned long frames[NR_GRANT_FRAMES];
145 int i;
147 for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
148 gnttab_list[i] = i + 1;
149 gnttab_free_head = NR_RESERVED_ENTRIES;
151 setup.dom = DOMID_SELF;
152 setup.nr_frames = NR_GRANT_FRAMES;
153 set_xen_guest_handle(setup.frame_list, frames);
155 HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
156 gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
157 printk("gnttab_table mapped at %p.\n", gnttab_table);
158 }