ia64/xen-unstable

view extras/mini-os/gnttab.c @ 19557:226ef307cd2e

AMD IOMMU: Fix ioapic interrupt remapping

A few ioapic redirection entries are initialized by hypervisor before
enabling iommu hardware. This patch copies those entries from ioapic
redirection table into interrupt remapping table after interrupt
remapping table has been allocated.

Signed-off-by: Wei Wang <wei.wang2@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Apr 17 13:16:39 2009 +0100 (2009-04-17)
parents a1c98534418b
children
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>
21 #include <semaphore.h>
23 #define NR_RESERVED_ENTRIES 8
25 /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
26 #ifdef __ia64__
27 #define NR_GRANT_FRAMES 1
28 #else
29 #define NR_GRANT_FRAMES 4
30 #endif
31 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
33 static grant_entry_t *gnttab_table;
34 static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
35 #ifdef GNT_DEBUG
36 static char inuse[NR_GRANT_ENTRIES];
37 #endif
38 static __DECLARE_SEMAPHORE_GENERIC(gnttab_sem, 0);
40 static void
41 put_free_entry(grant_ref_t ref)
42 {
43 unsigned long flags;
44 local_irq_save(flags);
45 #ifdef GNT_DEBUG
46 BUG_ON(!inuse[ref]);
47 inuse[ref] = 0;
48 #endif
49 gnttab_list[ref] = gnttab_list[0];
50 gnttab_list[0] = ref;
51 local_irq_restore(flags);
52 up(&gnttab_sem);
53 }
55 static grant_ref_t
56 get_free_entry(void)
57 {
58 unsigned int ref;
59 unsigned long flags;
60 down(&gnttab_sem);
61 local_irq_save(flags);
62 ref = gnttab_list[0];
63 BUG_ON(ref < NR_RESERVED_ENTRIES || ref >= NR_GRANT_ENTRIES);
64 gnttab_list[0] = gnttab_list[ref];
65 #ifdef GNT_DEBUG
66 BUG_ON(inuse[ref]);
67 inuse[ref] = 1;
68 #endif
69 local_irq_restore(flags);
70 return ref;
71 }
73 grant_ref_t
74 gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
75 {
76 grant_ref_t ref;
78 ref = get_free_entry();
79 gnttab_table[ref].frame = frame;
80 gnttab_table[ref].domid = domid;
81 wmb();
82 readonly *= GTF_readonly;
83 gnttab_table[ref].flags = GTF_permit_access | readonly;
85 return ref;
86 }
88 grant_ref_t
89 gnttab_grant_transfer(domid_t domid, unsigned long pfn)
90 {
91 grant_ref_t ref;
93 ref = get_free_entry();
94 gnttab_table[ref].frame = pfn;
95 gnttab_table[ref].domid = domid;
96 wmb();
97 gnttab_table[ref].flags = GTF_accept_transfer;
99 return ref;
100 }
102 int
103 gnttab_end_access(grant_ref_t ref)
104 {
105 u16 flags, nflags;
107 BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
109 nflags = gnttab_table[ref].flags;
110 do {
111 if ((flags = nflags) & (GTF_reading|GTF_writing)) {
112 printk("WARNING: g.e. still in use! (%x)\n", flags);
113 return 0;
114 }
115 } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
116 flags);
118 put_free_entry(ref);
119 return 1;
120 }
122 unsigned long
123 gnttab_end_transfer(grant_ref_t ref)
124 {
125 unsigned long frame;
126 u16 flags;
128 BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
130 while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
131 if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
132 printk("Release unused transfer grant.\n");
133 put_free_entry(ref);
134 return 0;
135 }
136 }
138 /* If a transfer is in progress then wait until it is completed. */
139 while (!(flags & GTF_transfer_completed)) {
140 flags = gnttab_table[ref].flags;
141 }
143 /* Read the frame number /after/ reading completion status. */
144 rmb();
145 frame = gnttab_table[ref].frame;
147 put_free_entry(ref);
149 return frame;
150 }
152 grant_ref_t
153 gnttab_alloc_and_grant(void **map)
154 {
155 unsigned long mfn;
156 grant_ref_t gref;
158 *map = (void *)alloc_page();
159 mfn = virt_to_mfn(*map);
160 gref = gnttab_grant_access(0, mfn, 0);
161 return gref;
162 }
164 static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
166 const char *
167 gnttabop_error(int16_t status)
168 {
169 status = -status;
170 if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
171 return "bad status";
172 else
173 return gnttabop_error_msgs[status];
174 }
176 void
177 init_gnttab(void)
178 {
179 struct gnttab_setup_table setup;
180 unsigned long frames[NR_GRANT_FRAMES];
181 int i;
183 #ifdef GNT_DEBUG
184 memset(inuse, 1, sizeof(inuse));
185 #endif
186 for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
187 put_free_entry(i);
189 setup.dom = DOMID_SELF;
190 setup.nr_frames = NR_GRANT_FRAMES;
191 set_xen_guest_handle(setup.frame_list, frames);
193 HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
194 gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
195 printk("gnttab_table mapped at %p.\n", gnttab_table);
196 }
198 void
199 fini_gnttab(void)
200 {
201 struct gnttab_setup_table setup;
203 setup.dom = DOMID_SELF;
204 setup.nr_frames = 0;
206 HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
207 }