direct-io.hg

view unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @ 11226:fc5736e0a2eb

[x86_64] Guests no longer set _PAGE_USER on kernel mappings.
This may allow guest kernels to be run outside ring 3 in future, and
also provides scope for optimisations today (e.g., using global bit on
user mappings).

Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Aug 22 15:26:40 2006 +0100 (2006-08-22)
parents b2f077bbca89
children 2b78726766d1
line source
1 /******************************************************************************
2 * evtchn-pci.c
3 * xen event channel fake PCI device driver
4 * Copyright (C) 2005, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 */
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/errno.h>
24 #include <linux/pci.h>
25 #include <linux/init.h>
26 #include <linux/version.h>
27 #include <linux/interrupt.h>
28 #include <asm/system.h>
29 #include <asm/io.h>
30 #include <asm/irq.h>
31 #include <asm/uaccess.h>
32 #include <asm/hypervisor.h>
33 #include <xen/interface/memory.h>
34 #include <xen/features.h>
36 #include "platform-pci.h"
38 #define DRV_NAME "xen-platform-pci"
39 #define DRV_VERSION "0.10"
40 #define DRV_RELDATE "03/03/2005"
42 char hypercall_page[PAGE_SIZE];
43 EXPORT_SYMBOL(hypercall_page);
45 // Used to be xiaofeng.ling@intel.com
46 MODULE_AUTHOR("ssmith@xensource.com");
47 MODULE_DESCRIPTION("Xen platform PCI device");
48 MODULE_LICENSE("GPL");
51 unsigned long *phys_to_machine_mapping;
52 EXPORT_SYMBOL(phys_to_machine_mapping);
54 static int __init init_xen_info(void)
55 {
56 unsigned long shared_info_frame;
57 struct xen_add_to_physmap xatp;
58 extern void *shared_info_area;
60 setup_xen_features();
62 shared_info_frame = alloc_xen_mmio(PAGE_SIZE) >> PAGE_SHIFT;
63 xatp.domid = DOMID_SELF;
64 xatp.idx = 0;
65 xatp.space = XENMAPSPACE_shared_info;
66 xatp.gpfn = shared_info_frame;
67 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
68 BUG();
70 shared_info_area =
71 ioremap(shared_info_frame << PAGE_SHIFT, PAGE_SIZE);
72 if (shared_info_area == NULL)
73 panic("can't map shared info\n");
75 phys_to_machine_mapping = NULL;
77 gnttab_init();
79 return 0;
80 }
82 static void __devexit platform_pci_remove(struct pci_dev *pdev)
83 {
84 long ioaddr, iolen;
85 long mmio_addr, mmio_len;
87 ioaddr = pci_resource_start(pdev, 0);
88 iolen = pci_resource_len(pdev, 0);
89 mmio_addr = pci_resource_start(pdev, 1);
90 mmio_len = pci_resource_len(pdev, 1);
92 release_region(ioaddr, iolen);
93 release_mem_region(mmio_addr, mmio_len);
95 pci_set_drvdata(pdev, NULL);
96 free_irq(pdev->irq, pdev);
97 }
99 static unsigned long platform_mmio;
100 static unsigned long platform_mmio_alloc;
101 static unsigned long platform_mmiolen;
103 unsigned long alloc_xen_mmio(unsigned long len)
104 {
105 unsigned long addr;
107 addr = 0;
108 if (platform_mmio_alloc + len <= platform_mmiolen)
109 {
110 addr = platform_mmio + platform_mmio_alloc;
111 platform_mmio_alloc += len;
112 } else {
113 panic("ran out of xen mmio space");
114 }
115 return addr;
116 }
118 /* Lifted from hvmloader.c */
119 static int get_hypercall_page(void)
120 {
121 void *tmp_hypercall_page;
122 uint32_t eax, ebx, ecx, edx;
123 char signature[13];
125 cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
126 *(uint32_t*)(signature + 0) = ebx;
127 *(uint32_t*)(signature + 4) = ecx;
128 *(uint32_t*)(signature + 8) = edx;
129 signature[12] = 0;
131 if (strcmp("XenVMMXenVMM", signature) || eax < 0x40000002) {
132 printk(KERN_WARNING
133 "Detected Xen platform device but not Xen VMM? (sig %s, eax %x)\n",
134 signature, eax);
135 return -EINVAL;
136 }
138 cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
140 printk(KERN_INFO "Xen version %d.%d.\n", eax >> 16, eax & 0xffff);
142 cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
144 if (eax != 1) {
145 printk(KERN_WARNING
146 "This Xen version uses a %d page hypercall area,"
147 "but these modules only support 1 page.\n",
148 eax);
149 return -EINVAL;
150 }
152 tmp_hypercall_page = (void *)__get_free_page(GFP_KERNEL);
153 if (!tmp_hypercall_page)
154 return -ENOMEM;
155 memset(tmp_hypercall_page, 0xcc, PAGE_SIZE);
156 if (wrmsr_safe(ebx, virt_to_phys(tmp_hypercall_page), 0))
157 panic("Can't do wrmsr; not running on Xen?\n");
158 memcpy(hypercall_page, tmp_hypercall_page, PAGE_SIZE);
159 free_page((unsigned long)tmp_hypercall_page);
161 return 0;
162 }
164 static int __devinit platform_pci_init(struct pci_dev *pdev,
165 const struct pci_device_id *ent)
166 {
167 int i, ret;
168 long ioaddr, iolen;
169 long mmio_addr, mmio_len;
171 i = pci_enable_device(pdev);
172 if (i)
173 return i;
175 ioaddr = pci_resource_start(pdev, 0);
176 iolen = pci_resource_len(pdev, 0);
178 mmio_addr = pci_resource_start(pdev, 1);
179 mmio_len = pci_resource_len(pdev, 1);
181 if (mmio_addr == 0 || ioaddr == 0) {
182 printk(KERN_WARNING DRV_NAME ":no resources found\n");
183 return -ENOENT;
184 }
186 if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL)
187 {
188 printk(KERN_ERR ":MEM I/O resource 0x%lx @ 0x%lx busy\n",
189 mmio_addr, mmio_len);
190 return -EBUSY;
191 }
193 if (request_region(ioaddr, iolen, DRV_NAME) == NULL)
194 {
195 printk(KERN_ERR DRV_NAME ":I/O resource 0x%lx @ 0x%lx busy\n",
196 iolen, ioaddr);
197 release_mem_region(mmio_addr, mmio_len);
198 return -EBUSY;
199 }
201 platform_mmio = mmio_addr;
202 platform_mmiolen = mmio_len;
204 ret = get_hypercall_page();
205 if (ret < 0)
206 goto out;
209 if ((ret = init_xen_info()))
210 goto out;
212 if ((ret = request_irq(pdev->irq, evtchn_interrupt, SA_SHIRQ,
213 "xen-platform-pci", pdev))) {
214 goto out;
215 }
217 if ((ret = set_callback_irq(pdev->irq)))
218 goto out;
220 out:
221 if (ret) {
222 release_mem_region(mmio_addr, mmio_len);
223 release_region(ioaddr, iolen);
224 }
226 return ret;
227 }
229 #define XEN_PLATFORM_VENDOR_ID 0xfffd
230 #define XEN_PLATFORM_DEVICE_ID 0x0101
231 static struct pci_device_id platform_pci_tbl[] __devinitdata = {
232 {XEN_PLATFORM_VENDOR_ID, XEN_PLATFORM_DEVICE_ID,
233 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
234 {0,}
235 };
237 MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
239 static struct pci_driver platform_driver = {
240 name: DRV_NAME,
241 probe: platform_pci_init,
242 remove: __devexit_p(platform_pci_remove),
243 id_table: platform_pci_tbl,
244 };
246 static int pci_device_registered;
248 static int __init platform_pci_module_init(void)
249 {
250 int rc;
252 rc = pci_module_init(&platform_driver);
253 if (rc)
254 printk(KERN_INFO DRV_NAME ":No platform pci device model found\n");
255 else
256 pci_device_registered = 1;
258 return rc;
259 }
261 static void __exit platform_pci_module_cleanup(void)
262 {
263 printk(KERN_INFO DRV_NAME ":Do platform module cleanup\n");
264 /* disable hypervisor for callback irq */
265 set_callback_irq(0);
266 if (pci_device_registered)
267 pci_unregister_driver(&platform_driver);
268 }
270 module_init(platform_pci_module_init);
271 module_exit(platform_pci_module_cleanup);