ia64/xen-unstable

view extras/mini-os/pcifront.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 1f338c90d60f
children 18c8270da77c
line source
1 /* Minimal PCI driver for Mini-OS.
2 * Copyright (c) 2007-2008 Samuel Thibault.
3 * Based on blkfront.c.
4 */
6 #include <os.h>
7 #include <xenbus.h>
8 #include <events.h>
9 #include <errno.h>
10 #include <gnttab.h>
11 #include <xmalloc.h>
12 #include <wait.h>
13 #include <pcifront.h>
15 #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
17 DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
19 struct pcifront_dev {
20 domid_t dom;
22 struct xen_pci_sharedinfo *info;
23 grant_ref_t info_ref;
24 evtchn_port_t evtchn;
26 char *nodename;
27 char *backend;
29 xenbus_event_queue events;
30 };
32 void pcifront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
33 {
34 wake_up(&pcifront_queue);
35 }
37 static void free_pcifront(struct pcifront_dev *dev)
38 {
39 mask_evtchn(dev->evtchn);
41 free(dev->backend);
43 gnttab_end_access(dev->info_ref);
44 free_page(dev->info);
46 unbind_evtchn(dev->evtchn);
48 free(dev->nodename);
49 free(dev);
50 }
52 struct pcifront_dev *init_pcifront(char *_nodename)
53 {
54 xenbus_transaction_t xbt;
55 char* err;
56 char* message=NULL;
57 int retry=0;
58 char* msg;
59 char* nodename = _nodename ? _nodename : "device/pci/0";
60 int dom;
62 struct pcifront_dev *dev;
64 char path[strlen(nodename) + 1 + 10 + 1];
66 printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
68 snprintf(path, sizeof(path), "%s/backend-id", nodename);
69 dom = xenbus_read_integer(path);
70 if (dom == -1) {
71 printk("no backend\n");
72 return NULL;
73 }
75 dev = malloc(sizeof(*dev));
76 memset(dev, 0, sizeof(*dev));
77 dev->nodename = strdup(nodename);
78 dev->dom = dom;
80 evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn);
82 dev->info = (struct xen_pci_sharedinfo*) alloc_page();
83 memset(dev->info,0,PAGE_SIZE);
85 dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0);
87 dev->events = NULL;
89 again:
90 err = xenbus_transaction_start(&xbt);
91 if (err) {
92 printk("starting transaction\n");
93 }
95 err = xenbus_printf(xbt, nodename, "pci-op-ref","%u",
96 dev->info_ref);
97 if (err) {
98 message = "writing pci-op-ref";
99 goto abort_transaction;
100 }
101 err = xenbus_printf(xbt, nodename,
102 "event-channel", "%u", dev->evtchn);
103 if (err) {
104 message = "writing event-channel";
105 goto abort_transaction;
106 }
107 err = xenbus_printf(xbt, nodename,
108 "magic", XEN_PCI_MAGIC);
109 if (err) {
110 message = "writing magic";
111 goto abort_transaction;
112 }
114 err = xenbus_printf(xbt, nodename, "state", "%u",
115 3); /* initialised */
118 err = xenbus_transaction_end(xbt, 0, &retry);
119 if (retry) {
120 goto again;
121 printk("completing transaction\n");
122 }
124 goto done;
126 abort_transaction:
127 xenbus_transaction_end(xbt, 1, &retry);
128 goto error;
130 done:
132 snprintf(path, sizeof(path), "%s/backend", nodename);
133 msg = xenbus_read(XBT_NIL, path, &dev->backend);
134 if (msg) {
135 printk("Error %s when reading the backend path %s\n", msg, path);
136 goto error;
137 }
139 printk("backend at %s\n", dev->backend);
141 {
142 char path[strlen(dev->backend) + 1 + 5 + 1];
143 snprintf(path, sizeof(path), "%s/state", dev->backend);
145 xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
147 xenbus_wait_for_value(path, "4", &dev->events);
149 xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
150 }
151 unmask_evtchn(dev->evtchn);
153 printk("**************************\n");
155 return dev;
157 error:
158 free_pcifront(dev);
159 return NULL;
160 }
162 void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun))
163 {
164 char path[strlen(dev->backend) + 1 + 5 + 10 + 1];
165 int i, n;
166 char *s, *msg;
167 unsigned int domain, bus, slot, fun;
169 snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
170 n = xenbus_read_integer(path);
172 for (i = 0; i < n; i++) {
173 snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
174 msg = xenbus_read(XBT_NIL, path, &s);
175 if (msg) {
176 printk("Error %s when reading the PCI root name at %s\n", path);
177 continue;
178 }
180 if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
181 printk("\"%s\" does not look like a PCI device address\n", s);
182 free(s);
183 continue;
184 }
185 free(s);
187 func(domain, bus, slot, fun);
188 }
189 }
191 void shutdown_pcifront(struct pcifront_dev *dev)
192 {
193 char* err;
194 char *nodename = dev->nodename;
196 char path[strlen(dev->backend) + 1 + 5 + 1];
198 printk("close pci: backend at %s\n",dev->backend);
200 snprintf(path, sizeof(path), "%s/state", dev->backend);
201 err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
202 xenbus_wait_for_value(path, "5", &dev->events);
204 err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
205 xenbus_wait_for_value(path, "6", &dev->events);
207 err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
208 xenbus_wait_for_value(path, "2", &dev->events);
210 xenbus_unwatch_path(XBT_NIL, path);
212 snprintf(path, sizeof(path), "%s/info-ref", nodename);
213 xenbus_rm(XBT_NIL, path);
214 snprintf(path, sizeof(path), "%s/event-channel", nodename);
215 xenbus_rm(XBT_NIL, path);
217 free_pcifront(dev);
218 }
221 void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
222 {
223 dev->info->op = *op;
224 /* Make sure info is written before the flag */
225 wmb();
226 set_bit(_XEN_PCIF_active, (void*) &dev->info->flags);
227 notify_remote_via_evtchn(dev->evtchn);
229 wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, (void*) &dev->info->flags));
231 /* Make sure flag is read before info */
232 rmb();
233 *op = dev->info->op;
234 }
236 int pcifront_conf_read(struct pcifront_dev *dev,
237 unsigned int dom,
238 unsigned int bus, unsigned int slot, unsigned long fun,
239 unsigned int off, unsigned int size, unsigned int *val)
240 {
241 struct xen_pci_op op;
243 memset(&op, 0, sizeof(op));
245 op.cmd = XEN_PCI_OP_conf_read;
246 op.domain = dom;
247 op.bus = bus;
248 op.devfn = PCI_DEVFN(slot, fun);
249 op.offset = off;
250 op.size = size;
252 pcifront_op(dev, &op);
254 if (op.err)
255 return op.err;
257 *val = op.value;
259 return 0;
260 }
262 int pcifront_conf_write(struct pcifront_dev *dev,
263 unsigned int dom,
264 unsigned int bus, unsigned int slot, unsigned long fun,
265 unsigned int off, unsigned int size, unsigned int val)
266 {
267 struct xen_pci_op op;
269 memset(&op, 0, sizeof(op));
271 op.cmd = XEN_PCI_OP_conf_write;
272 op.domain = dom;
273 op.bus = bus;
274 op.devfn = PCI_DEVFN(slot, fun);
275 op.offset = off;
276 op.size = size;
278 op.value = val;
280 pcifront_op(dev, &op);
282 return op.err;
283 }
285 int pcifront_enable_msi(struct pcifront_dev *dev,
286 unsigned int dom,
287 unsigned int bus, unsigned int slot, unsigned long fun)
288 {
289 struct xen_pci_op op;
291 memset(&op, 0, sizeof(op));
293 op.cmd = XEN_PCI_OP_enable_msi;
294 op.domain = dom;
295 op.bus = bus;
296 op.devfn = PCI_DEVFN(slot, fun);
298 pcifront_op(dev, &op);
300 if (op.err)
301 return op.err;
302 else
303 return op.value;
304 }
306 int pcifront_disable_msi(struct pcifront_dev *dev,
307 unsigned int dom,
308 unsigned int bus, unsigned int slot, unsigned long fun)
309 {
310 struct xen_pci_op op;
312 memset(&op, 0, sizeof(op));
314 op.cmd = XEN_PCI_OP_disable_msi;
315 op.domain = dom;
316 op.bus = bus;
317 op.devfn = PCI_DEVFN(slot, fun);
319 pcifront_op(dev, &op);
321 return op.err;
322 }
324 int pcifront_enable_msix(struct pcifront_dev *dev,
325 unsigned int dom,
326 unsigned int bus, unsigned int slot, unsigned long fun,
327 struct xen_msix_entry *entries, int n)
328 {
329 struct xen_pci_op op;
331 if (n > SH_INFO_MAX_VEC)
332 return XEN_PCI_ERR_op_failed;
334 memset(&op, 0, sizeof(op));
336 op.cmd = XEN_PCI_OP_enable_msix;
337 op.domain = dom;
338 op.bus = bus;
339 op.devfn = PCI_DEVFN(slot, fun);
340 op.value = n;
342 memcpy(op.msix_entries, entries, n * sizeof(*entries));
344 pcifront_op(dev, &op);
346 if (op.err)
347 return op.err;
349 memcpy(entries, op.msix_entries, n * sizeof(*entries));
351 return 0;
352 }
355 int pcifront_disable_msix(struct pcifront_dev *dev,
356 unsigned int dom,
357 unsigned int bus, unsigned int slot, unsigned long fun)
358 {
359 struct xen_pci_op op;
361 memset(&op, 0, sizeof(op));
363 op.cmd = XEN_PCI_OP_disable_msix;
364 op.domain = dom;
365 op.bus = bus;
366 op.devfn = PCI_DEVFN(slot, fun);
368 pcifront_op(dev, &op);
370 return op.err;
371 }