aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/xen/Kconfig9
-rw-r--r--drivers/xen/Makefile3
-rw-r--r--drivers/xen/events.c8
-rw-r--r--drivers/xen/grant-table.c77
-rw-r--r--drivers/xen/manage.c1
-rw-r--r--drivers/xen/platform-pci.c181
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c22
-rw-r--r--include/linux/pci_ids.h3
-rw-r--r--include/xen/grant_table.h4
-rw-r--r--include/xen/interface/grant_table.h1
10 files changed, 291 insertions, 18 deletions
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index fad3df2c1276..8f84b108b491 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -62,4 +62,13 @@ config XEN_SYS_HYPERVISOR
62 virtual environment, /sys/hypervisor will still be present, 62 virtual environment, /sys/hypervisor will still be present,
63 but will have no xen contents. 63 but will have no xen contents.
64 64
65config XEN_PLATFORM_PCI
66 tristate "xen platform pci device driver"
67 depends on XEN
68 default m
69 help
70 Driver for the Xen PCI Platform device: it is responsible for
71 initializing xenbus and grant_table when running in a Xen HVM
72 domain. As a consequence this driver is required to run any Xen PV
73 frontend on Xen HVM.
65endmenu 74endmenu
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 7c284342f30f..e392fb776af3 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
9obj-$(CONFIG_XEN_BALLOON) += balloon.o 9obj-$(CONFIG_XEN_BALLOON) += balloon.o
10obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o 10obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o
11obj-$(CONFIG_XENFS) += xenfs/ 11obj-$(CONFIG_XENFS) += xenfs/
12obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o \ No newline at end of file 12obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
13obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index d659480125f0..7c64473c9f3f 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -665,7 +665,7 @@ static void __xen_evtchn_do_upcall(void)
665 665
666 count = __get_cpu_var(xed_nesting_count); 666 count = __get_cpu_var(xed_nesting_count);
667 __get_cpu_var(xed_nesting_count) = 0; 667 __get_cpu_var(xed_nesting_count) = 0;
668 } while(count != 1); 668 } while (count != 1 || vcpu_info->evtchn_upcall_pending);
669 669
670out: 670out:
671 671
@@ -689,6 +689,7 @@ void xen_hvm_evtchn_do_upcall(void)
689{ 689{
690 __xen_evtchn_do_upcall(); 690 __xen_evtchn_do_upcall();
691} 691}
692EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
692 693
693/* Rebind a new event channel to an existing irq. */ 694/* Rebind a new event channel to an existing irq. */
694void rebind_evtchn_irq(int evtchn, int irq) 695void rebind_evtchn_irq(int evtchn, int irq)
@@ -725,7 +726,10 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
725 struct evtchn_bind_vcpu bind_vcpu; 726 struct evtchn_bind_vcpu bind_vcpu;
726 int evtchn = evtchn_from_irq(irq); 727 int evtchn = evtchn_from_irq(irq);
727 728
728 if (!VALID_EVTCHN(evtchn)) 729 /* events delivered via platform PCI interrupts are always
730 * routed to vcpu 0 */
731 if (!VALID_EVTCHN(evtchn) ||
732 (xen_hvm_domain() && !xen_have_vector_callback))
729 return -1; 733 return -1;
730 734
731 /* Send future instances of this interrupt to other vcpu. */ 735 /* Send future instances of this interrupt to other vcpu. */
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index f66db3b91d61..6c4531816496 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -37,11 +37,13 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/uaccess.h> 39#include <linux/uaccess.h>
40#include <linux/io.h>
40 41
41#include <xen/xen.h> 42#include <xen/xen.h>
42#include <xen/interface/xen.h> 43#include <xen/interface/xen.h>
43#include <xen/page.h> 44#include <xen/page.h>
44#include <xen/grant_table.h> 45#include <xen/grant_table.h>
46#include <xen/interface/memory.h>
45#include <asm/xen/hypercall.h> 47#include <asm/xen/hypercall.h>
46 48
47#include <asm/pgtable.h> 49#include <asm/pgtable.h>
@@ -59,6 +61,8 @@ static unsigned int boot_max_nr_grant_frames;
59static int gnttab_free_count; 61static int gnttab_free_count;
60static grant_ref_t gnttab_free_head; 62static grant_ref_t gnttab_free_head;
61static DEFINE_SPINLOCK(gnttab_list_lock); 63static DEFINE_SPINLOCK(gnttab_list_lock);
64unsigned long xen_hvm_resume_frames;
65EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
62 66
63static struct grant_entry *shared; 67static struct grant_entry *shared;
64 68
@@ -433,7 +437,7 @@ static unsigned int __max_nr_grant_frames(void)
433 return query.max_nr_frames; 437 return query.max_nr_frames;
434} 438}
435 439
436static inline unsigned int max_nr_grant_frames(void) 440unsigned int gnttab_max_grant_frames(void)
437{ 441{
438 unsigned int xen_max = __max_nr_grant_frames(); 442 unsigned int xen_max = __max_nr_grant_frames();
439 443
@@ -441,6 +445,7 @@ static inline unsigned int max_nr_grant_frames(void)
441 return boot_max_nr_grant_frames; 445 return boot_max_nr_grant_frames;
442 return xen_max; 446 return xen_max;
443} 447}
448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
444 449
445static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 450static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
446{ 451{
@@ -449,6 +454,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
449 unsigned int nr_gframes = end_idx + 1; 454 unsigned int nr_gframes = end_idx + 1;
450 int rc; 455 int rc;
451 456
457 if (xen_hvm_domain()) {
458 struct xen_add_to_physmap xatp;
459 unsigned int i = end_idx;
460 rc = 0;
461 /*
462 * Loop backwards, so that the first hypercall has the largest
463 * index, ensuring that the table will grow only once.
464 */
465 do {
466 xatp.domid = DOMID_SELF;
467 xatp.idx = i;
468 xatp.space = XENMAPSPACE_grant_table;
469 xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
470 rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
471 if (rc != 0) {
472 printk(KERN_WARNING
473 "grant table add_to_physmap failed, err=%d\n", rc);
474 break;
475 }
476 } while (i-- > start_idx);
477
478 return rc;
479 }
480
452 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); 481 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
453 if (!frames) 482 if (!frames)
454 return -ENOMEM; 483 return -ENOMEM;
@@ -465,7 +494,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
465 494
466 BUG_ON(rc || setup.status); 495 BUG_ON(rc || setup.status);
467 496
468 rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(), 497 rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(),
469 &shared); 498 &shared);
470 BUG_ON(rc); 499 BUG_ON(rc);
471 500
@@ -476,9 +505,27 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
476 505
477int gnttab_resume(void) 506int gnttab_resume(void)
478{ 507{
479 if (max_nr_grant_frames() < nr_grant_frames) 508 unsigned int max_nr_gframes;
509
510 max_nr_gframes = gnttab_max_grant_frames();
511 if (max_nr_gframes < nr_grant_frames)
480 return -ENOSYS; 512 return -ENOSYS;
481 return gnttab_map(0, nr_grant_frames - 1); 513
514 if (xen_pv_domain())
515 return gnttab_map(0, nr_grant_frames - 1);
516
517 if (!shared) {
518 shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes);
519 if (shared == NULL) {
520 printk(KERN_WARNING
521 "Failed to ioremap gnttab share frames!");
522 return -ENOMEM;
523 }
524 }
525
526 gnttab_map(0, nr_grant_frames - 1);
527
528 return 0;
482} 529}
483 530
484int gnttab_suspend(void) 531int gnttab_suspend(void)
@@ -495,7 +542,7 @@ static int gnttab_expand(unsigned int req_entries)
495 cur = nr_grant_frames; 542 cur = nr_grant_frames;
496 extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / 543 extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
497 GREFS_PER_GRANT_FRAME); 544 GREFS_PER_GRANT_FRAME);
498 if (cur + extra > max_nr_grant_frames()) 545 if (cur + extra > gnttab_max_grant_frames())
499 return -ENOSPC; 546 return -ENOSPC;
500 547
501 rc = gnttab_map(cur, cur + extra - 1); 548 rc = gnttab_map(cur, cur + extra - 1);
@@ -505,15 +552,12 @@ static int gnttab_expand(unsigned int req_entries)
505 return rc; 552 return rc;
506} 553}
507 554
508static int __devinit gnttab_init(void) 555int gnttab_init(void)
509{ 556{
510 int i; 557 int i;
511 unsigned int max_nr_glist_frames, nr_glist_frames; 558 unsigned int max_nr_glist_frames, nr_glist_frames;
512 unsigned int nr_init_grefs; 559 unsigned int nr_init_grefs;
513 560
514 if (!xen_domain())
515 return -ENODEV;
516
517 nr_grant_frames = 1; 561 nr_grant_frames = 1;
518 boot_max_nr_grant_frames = __max_nr_grant_frames(); 562 boot_max_nr_grant_frames = __max_nr_grant_frames();
519 563
@@ -556,5 +600,18 @@ static int __devinit gnttab_init(void)
556 kfree(gnttab_list); 600 kfree(gnttab_list);
557 return -ENOMEM; 601 return -ENOMEM;
558} 602}
603EXPORT_SYMBOL_GPL(gnttab_init);
604
605static int __devinit __gnttab_init(void)
606{
607 /* Delay grant-table initialization in the PV on HVM case */
608 if (xen_hvm_domain())
609 return 0;
610
611 if (!xen_pv_domain())
612 return -ENODEV;
613
614 return gnttab_init();
615}
559 616
560core_initcall(gnttab_init); 617core_initcall(__gnttab_init);
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 07e857b0de13..af9c5594d315 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -264,5 +264,6 @@ static int __init setup_shutdown_event(void)
264 264
265 return 0; 265 return 0;
266} 266}
267EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
267 268
268subsys_initcall(setup_shutdown_event); 269subsys_initcall(setup_shutdown_event);
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
new file mode 100644
index 000000000000..a0ee5d06f715
--- /dev/null
+++ b/drivers/xen/platform-pci.c
@@ -0,0 +1,181 @@
1/******************************************************************************
2 * platform-pci.c
3 *
4 * Xen platform PCI device driver
5 * Copyright (c) 2005, Intel Corporation.
6 * Copyright (c) 2007, XenSource Inc.
7 * Copyright (c) 2010, Citrix
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 * Place - Suite 330, Boston, MA 02111-1307 USA.
21 *
22 */
23
24
25#include <linux/interrupt.h>
26#include <linux/io.h>
27#include <linux/module.h>
28#include <linux/pci.h>
29
30#include <xen/grant_table.h>
31#include <xen/xenbus.h>
32#include <xen/events.h>
33#include <xen/hvm.h>
34
35#define DRV_NAME "xen-platform-pci"
36
37MODULE_AUTHOR("ssmith@xensource.com and stefano.stabellini@eu.citrix.com");
38MODULE_DESCRIPTION("Xen platform PCI device");
39MODULE_LICENSE("GPL");
40
41static unsigned long platform_mmio;
42static unsigned long platform_mmio_alloc;
43static unsigned long platform_mmiolen;
44
45unsigned long alloc_xen_mmio(unsigned long len)
46{
47 unsigned long addr;
48
49 addr = platform_mmio + platform_mmio_alloc;
50 platform_mmio_alloc += len;
51 BUG_ON(platform_mmio_alloc > platform_mmiolen);
52
53 return addr;
54}
55
56static uint64_t get_callback_via(struct pci_dev *pdev)
57{
58 u8 pin;
59 int irq;
60
61 irq = pdev->irq;
62 if (irq < 16)
63 return irq; /* ISA IRQ */
64
65 pin = pdev->pin;
66
67 /* We don't know the GSI. Specify the PCI INTx line instead. */
68 return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
69 ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
70 ((uint64_t)pdev->bus->number << 16) |
71 ((uint64_t)(pdev->devfn & 0xff) << 8) |
72 ((uint64_t)(pin - 1) & 3);
73}
74
75static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
76{
77 xen_hvm_evtchn_do_upcall();
78 return IRQ_HANDLED;
79}
80
81static int xen_allocate_irq(struct pci_dev *pdev)
82{
83 return request_irq(pdev->irq, do_hvm_evtchn_intr,
84 IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
85 "xen-platform-pci", pdev);
86}
87
88static int __devinit platform_pci_init(struct pci_dev *pdev,
89 const struct pci_device_id *ent)
90{
91 int i, ret;
92 long ioaddr, iolen;
93 long mmio_addr, mmio_len;
94 uint64_t callback_via;
95 unsigned int max_nr_gframes;
96
97 i = pci_enable_device(pdev);
98 if (i)
99 return i;
100
101 ioaddr = pci_resource_start(pdev, 0);
102 iolen = pci_resource_len(pdev, 0);
103
104 mmio_addr = pci_resource_start(pdev, 1);
105 mmio_len = pci_resource_len(pdev, 1);
106
107 if (mmio_addr == 0 || ioaddr == 0) {
108 dev_err(&pdev->dev, "no resources found\n");
109 ret = -ENOENT;
110 goto pci_out;
111 }
112
113 if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) {
114 dev_err(&pdev->dev, "MEM I/O resource 0x%lx @ 0x%lx busy\n",
115 mmio_addr, mmio_len);
116 ret = -EBUSY;
117 goto pci_out;
118 }
119
120 if (request_region(ioaddr, iolen, DRV_NAME) == NULL) {
121 dev_err(&pdev->dev, "I/O resource 0x%lx @ 0x%lx busy\n",
122 iolen, ioaddr);
123 ret = -EBUSY;
124 goto mem_out;
125 }
126
127 platform_mmio = mmio_addr;
128 platform_mmiolen = mmio_len;
129
130 if (!xen_have_vector_callback) {
131 ret = xen_allocate_irq(pdev);
132 if (ret) {
133 dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
134 goto out;
135 }
136 callback_via = get_callback_via(pdev);
137 ret = xen_set_callback_via(callback_via);
138 if (ret) {
139 dev_warn(&pdev->dev, "Unable to set the evtchn callback "
140 "err=%d\n", ret);
141 goto out;
142 }
143 }
144
145 max_nr_gframes = gnttab_max_grant_frames();
146 xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
147 ret = gnttab_init();
148 if (ret)
149 goto out;
150 xenbus_probe(NULL);
151 return 0;
152
153out:
154 release_region(ioaddr, iolen);
155mem_out:
156 release_mem_region(mmio_addr, mmio_len);
157pci_out:
158 pci_disable_device(pdev);
159 return ret;
160}
161
162static struct pci_device_id platform_pci_tbl[] __devinitdata = {
163 {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
164 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
165 {0,}
166};
167
168MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
169
170static struct pci_driver platform_driver = {
171 .name = DRV_NAME,
172 .probe = platform_pci_init,
173 .id_table = platform_pci_tbl,
174};
175
176static int __init platform_pci_module_init(void)
177{
178 return pci_register_driver(&platform_driver);
179}
180
181module_init(platform_pci_module_init);
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index d96fa75b45ec..a9e83c438cbb 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -781,8 +781,23 @@ void xenbus_probe(struct work_struct *unused)
781 /* Notify others that xenstore is up */ 781 /* Notify others that xenstore is up */
782 blocking_notifier_call_chain(&xenstore_chain, 0, NULL); 782 blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
783} 783}
784EXPORT_SYMBOL_GPL(xenbus_probe);
784 785
785static int __init xenbus_probe_init(void) 786static int __init xenbus_probe_initcall(void)
787{
788 if (!xen_domain())
789 return -ENODEV;
790
791 if (xen_initial_domain() || xen_hvm_domain())
792 return 0;
793
794 xenbus_probe(NULL);
795 return 0;
796}
797
798device_initcall(xenbus_probe_initcall);
799
800static int __init xenbus_init(void)
786{ 801{
787 int err = 0; 802 int err = 0;
788 803
@@ -834,9 +849,6 @@ static int __init xenbus_probe_init(void)
834 goto out_unreg_back; 849 goto out_unreg_back;
835 } 850 }
836 851
837 if (!xen_initial_domain())
838 xenbus_probe(NULL);
839
840#ifdef CONFIG_XEN_COMPAT_XENFS 852#ifdef CONFIG_XEN_COMPAT_XENFS
841 /* 853 /*
842 * Create xenfs mountpoint in /proc for compatibility with 854 * Create xenfs mountpoint in /proc for compatibility with
@@ -857,7 +869,7 @@ static int __init xenbus_probe_init(void)
857 return err; 869 return err;
858} 870}
859 871
860postcore_initcall(xenbus_probe_init); 872postcore_initcall(xenbus_init);
861 873
862MODULE_LICENSE("GPL"); 874MODULE_LICENSE("GPL");
863 875
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 3bedcc149c84..cca2526f28d7 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2772,3 +2772,6 @@
2772#define PCI_DEVICE_ID_RME_DIGI32 0x9896 2772#define PCI_DEVICE_ID_RME_DIGI32 0x9896
2773#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 2773#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897
2774#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 2774#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898
2775
2776#define PCI_VENDOR_ID_XEN 0x5853
2777#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index a40f1cd91be1..9a731706a016 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -51,6 +51,7 @@ struct gnttab_free_callback {
51 u16 count; 51 u16 count;
52}; 52};
53 53
54int gnttab_init(void);
54int gnttab_suspend(void); 55int gnttab_suspend(void);
55int gnttab_resume(void); 56int gnttab_resume(void);
56 57
@@ -112,6 +113,9 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
112void arch_gnttab_unmap_shared(struct grant_entry *shared, 113void arch_gnttab_unmap_shared(struct grant_entry *shared,
113 unsigned long nr_gframes); 114 unsigned long nr_gframes);
114 115
116extern unsigned long xen_hvm_resume_frames;
117unsigned int gnttab_max_grant_frames(void);
118
115#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) 119#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
116 120
117#endif /* __ASM_GNTTAB_H__ */ 121#endif /* __ASM_GNTTAB_H__ */
diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
index 39da93c21de0..39e571796e32 100644
--- a/include/xen/interface/grant_table.h
+++ b/include/xen/interface/grant_table.h
@@ -28,6 +28,7 @@
28#ifndef __XEN_PUBLIC_GRANT_TABLE_H__ 28#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
29#define __XEN_PUBLIC_GRANT_TABLE_H__ 29#define __XEN_PUBLIC_GRANT_TABLE_H__
30 30
31#include <xen/interface/xen.h>
31 32
32/*********************************** 33/***********************************
33 * GRANT TABLE REPRESENTATION 34 * GRANT TABLE REPRESENTATION