kvm: release: merge from trunk
[kvm-userspace.git] / drivers / hypercall.c
blobe5f4c8b56ddd51704ab5d22efb2b4492de529ea5
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/compiler.h>
5 #include <linux/pci.h>
6 #include <linux/init.h>
7 #include <linux/ioport.h>
8 #include <linux/completion.h>
9 #include <linux/interrupt.h>
10 #include <asm/io.h>
11 #include <asm/uaccess.h>
12 #include <asm/irq.h>
14 #define HYPERCALL_DRIVER_NAME "Qumranet_hypercall_driver"
15 #define HYPERCALL_DRIVER_VERSION "1"
16 #define PCI_VENDOR_ID_HYPERCALL 0x5002
17 #define PCI_DEVICE_ID_HYPERCALL 0x2258
19 MODULE_AUTHOR ("Dor Laor <dor.laor@qumranet.com>");
20 MODULE_DESCRIPTION (HYPERCALL_DRIVER_NAME);
21 MODULE_LICENSE("GPL");
22 MODULE_VERSION(HYPERCALL_DRIVER_VERSION);
24 static int debug = 0;
25 module_param(debug, int, 0);
26 MODULE_PARM_DESC (debug, "toggle debug flag");
28 #define HYPERCALL_DEBUG 1
29 #if HYPERCALL_DEBUG
30 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
31 # define assert(expr) \
32 if(unlikely(!(expr))) { \
33 printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
34 #expr,__FILE__,__FUNCTION__,__LINE__); \
36 #else
37 # define DPRINTK(fmt, args...)
38 # define assert(expr) do {} while (0)
39 #endif
41 static struct pci_device_id hypercall_pci_tbl[] = {
42 {PCI_VENDOR_ID_HYPERCALL, PCI_DEVICE_ID_HYPERCALL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
43 {0,}
45 MODULE_DEVICE_TABLE (pci, hypercall_pci_tbl);
49 /****** Hypercall device definitions ***************/
50 /* To be moved into a shared file with user space */
51 #define HP_CMD 0x00 // The command register WR
52 #define HP_ISRSTATUS 0x04 // Interrupt status reg RD
53 #define HP_TXSIZE 0x08
54 #define HP_TXBUFF 0x0c
55 #define HP_RXSIZE 0x10
56 #define HP_RXBUFF 0x14
58 // HP_CMD register commands
59 #define HP_CMD_DI 1 // disable interrupts
60 #define HP_CMD_EI 2 // enable interrupts
61 #define HP_CMD_INIT 4 // reset device
62 #define HP_CMD_RESET (HP_CMD_INIT|HP_CMD_DI)
64 /* Bits in HP_ISR - Interrupt status register */
65 #define HPISR_RX 0x01 // Data is ready to be read
67 #define HP_MEM_SIZE 0xE0
68 /******* End of Hypercall device definitions */
70 /* read PIO/MMIO register */
71 #define HIO_READ8(reg, ioaddr) ioread8(ioaddr + (reg))
72 #define HIO_READ16(reg, ioaddr) ioread16(ioaddr + (reg))
73 #define HIO_READ32(reg, ioaddr) ioread32(ioaddr + (reg))
75 /* write PIO/MMIO register */
76 #define HIO_WRITE8(reg, val8, ioaddr) iowrite8((val8), ioaddr + (reg))
77 #define HIO_WRITE16(reg, val16, ioaddr) iowrite16((val16), ioaddr + (reg))
78 #define HIO_WRITE32(reg, val32, ioaddr) iowrite32((val32), ioaddr + (reg))
81 struct hypercall_dev {
82 struct pci_dev *pci_dev;
83 struct kobject kobject;
84 u32 state;
85 spinlock_t lock;
86 u8 name[128];
87 u16 irq;
88 u32 regs_len;
89 void __iomem *io_addr;
90 unsigned long base_addr; /* device I/O address */
91 unsigned long cmd;
95 static int hypercall_close(struct hypercall_dev* dev);
96 static int hypercall_open(struct hypercall_dev *dev);
97 static void hypercall_cleanup_dev(struct hypercall_dev *dev);
98 static irqreturn_t hypercall_interrupt(int irq, void *dev_instance,
99 struct pt_regs *regs);
101 static void __exit hypercall_sysfs_remove(struct hypercall_dev *dev);
102 static int hypercall_sysfs_add(struct hypercall_dev *dev);
105 static int __devinit hypercall_init_board(struct pci_dev *pdev,
106 struct hypercall_dev **dev_out)
108 unsigned long ioaddr;
109 struct hypercall_dev *dev;
110 int rc;
111 u32 disable_dev_on_err = 0;
112 unsigned long pio_start, pio_end, pio_flags, pio_len;
113 unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
115 assert(pdev != NULL);
117 *dev_out = NULL;
119 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
120 if (dev == NULL) {
121 printk (KERN_ERR "%s: Unable to alloc hypercall device\n", pci_name(pdev));
122 return -ENOMEM;
124 dev->pci_dev = pdev;
125 rc = pci_enable_device(pdev);
126 if (rc)
127 goto err_out;
128 disable_dev_on_err = 1;
130 pio_start = pci_resource_start (pdev, 0);
131 pio_end = pci_resource_end (pdev, 0);
132 pio_flags = pci_resource_flags (pdev, 0);
133 pio_len = pci_resource_len (pdev, 0);
135 mmio_start = pci_resource_start (pdev, 1);
136 mmio_end = pci_resource_end (pdev, 1);
137 mmio_flags = pci_resource_flags (pdev, 1);
138 mmio_len = pci_resource_len (pdev, 1);
140 DPRINTK("PIO region size == 0x%02lX\n", pio_len);
141 DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
143 rc = pci_request_regions (pdev, "hypercall");
144 if (rc)
145 goto err_out;
147 #define USE_IO_OPS 1
148 #ifdef USE_IO_OPS
149 ioaddr = (unsigned long)pci_iomap(pdev, 0, 0);
150 //ioaddr = ioport_map(pio_start, pio_len);
151 if (!ioaddr) {
152 printk(KERN_ERR "%s: cannot map PIO, aborting\n", pci_name(pdev));
153 rc = -EIO;
154 goto err_out;
156 dev->base_addr = (unsigned long)pio_start;
157 dev->io_addr = (void*)ioaddr;
158 dev->regs_len = pio_len;
159 #else
160 ioaddr = pci_iomap(pdev, 1, 0);
161 if (ioaddr == NULL) {
162 printk(KERN_ERR "%s: cannot remap MMIO, aborting\n", pci_name(pdev));
163 rc = -EIO;
164 goto err_out;
166 dev->base_addr = ioaddr;
167 dev->io_addr = (void*)ioaddr;
168 dev->regs_len = mmio_len;
169 #endif /* USE_IO_OPS */
171 *dev_out = dev;
172 return 0;
174 err_out:
175 hypercall_cleanup_dev(dev);
176 if (disable_dev_on_err)
177 pci_disable_device(pdev);
178 return rc;
181 static int __devinit hypercall_init_one(struct pci_dev *pdev,
182 const struct pci_device_id *ent)
184 struct hypercall_dev *dev;
185 u8 pci_rev;
187 assert(pdev != NULL);
188 assert(ent != NULL);
190 pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
192 if (pdev->vendor == PCI_VENDOR_ID_HYPERCALL &&
193 pdev->device == PCI_DEVICE_ID_HYPERCALL) {
194 printk(KERN_INFO "pci dev %s (id %04x:%04x rev %02x) is a guest hypercall device\n",
195 pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
198 if (hypercall_init_board(pdev, &dev) != 0)
199 return -1;
201 assert(dev != NULL);
203 dev->irq = pdev->irq;
205 spin_lock_init(&dev->lock);
206 pci_set_drvdata(pdev, dev);
208 printk (KERN_INFO "name=%s: base_addr=0x%lx, io_addr=0x%lx, IRQ=%d\n",
209 dev->name, dev->base_addr, (unsigned long)dev->io_addr, dev->irq);
210 hypercall_open(dev);
212 if (hypercall_sysfs_add(dev) != 0)
213 return -1;
215 return 0;
218 static void __devexit hypercall_remove_one(struct pci_dev *pdev)
220 struct hypercall_dev *dev = pci_get_drvdata(pdev);
222 assert(dev != NULL);
224 hypercall_close(dev);
225 hypercall_sysfs_remove(dev);
226 hypercall_cleanup_dev(dev);
227 pci_disable_device(pdev);
230 static int hypercall_tx(struct hypercall_dev *dev, unsigned char *buf, size_t len)
232 void __iomem *ioaddr = (void __iomem*)dev->io_addr;
233 int i;
235 if (len > HP_MEM_SIZE)
236 return -EINVAL;
238 spin_lock(&dev->lock);
239 HIO_WRITE8(HP_TXSIZE, len, ioaddr);
240 for (i=0; i< len; i++)
241 HIO_WRITE8(HP_TXBUFF, buf[i], ioaddr);
242 spin_unlock(&dev->lock);
244 return 0;
248 * The interrupt handler does all of the rx work and cleans up
249 * after the tx
251 static irqreturn_t hypercall_interrupt(int irq, void *dev_instance,
252 struct pt_regs *regs)
254 struct hypercall_dev *dev = (struct hypercall_dev *)dev_instance;
255 void __iomem *ioaddr = (void __iomem*)dev->io_addr;
256 u32 status;
257 int irq_handled = IRQ_NONE;
258 int rx_buf_size;
259 int i;
260 u8 buffer[HP_MEM_SIZE];
261 u8 *pbuf;
263 DPRINTK("base addr is 0x%lx, io_addr=0x%lx\n", dev->base_addr, (long)dev->io_addr);
265 spin_lock(&dev->lock);
266 status = HIO_READ8(HP_ISRSTATUS, ioaddr);
267 DPRINTK("irq status is 0x%x\n", status);
269 /* shared irq? */
270 if (unlikely((status & HPISR_RX) == 0)) {
271 DPRINTK("not handeling irq, not ours\n");
272 goto out;
275 /* Disable device interrupts */
276 HIO_WRITE8(HP_CMD, HP_CMD_DI, ioaddr);
277 DPRINTK("disable device interrupts\n");
279 rx_buf_size = HIO_READ8(HP_RXSIZE, ioaddr);
280 DPRINTK("Rx buffer size is %d\n", rx_buf_size);
282 if (rx_buf_size > HP_MEM_SIZE)
283 rx_buf_size = HP_MEM_SIZE;
285 for (i=0, pbuf=buffer; i<rx_buf_size; i++, pbuf++) {
286 *pbuf = HIO_READ8(HP_RXBUFF, ioaddr + i);
287 DPRINTK("Read 0x%x as dword %d\n", *pbuf, i);
289 *pbuf = '\0';
290 DPRINTK("Read buffer %s", (char*)buffer);
292 HIO_WRITE8(HP_CMD, HP_CMD_EI, ioaddr);
293 DPRINTK("Enable interrupt\n");
294 irq_handled = IRQ_HANDLED;
295 out:
296 spin_unlock(&dev->lock);
299 hypercall_tx(dev, "hello host", sizeof("hello host"));
300 return irq_handled;
304 static int hypercall_open(struct hypercall_dev *dev)
306 int rc;
308 rc = request_irq(dev->irq, &hypercall_interrupt,
309 SA_SHIRQ, dev->name, dev);
310 if (rc) {
311 printk(KERN_ERR "%s failed to request an irq\n", __FUNCTION__);
312 return rc;
315 //hypercall_thread_start(dev);
317 return 0;
320 static int hypercall_close(struct hypercall_dev* dev)
322 //hypercall_thread_stop(dev);
323 synchronize_irq(dev->irq);
324 free_irq(dev->irq, dev);
326 return 0;
329 #ifdef CONFIG_PM
331 static int hypercall_suspend(struct pci_dev *pdev, pm_message_t state)
333 pci_save_state(pdev);
334 pci_set_power_state(pdev, PCI_D3hot);
335 DPRINTK("Power mgmt suspend, set power state to PCI_D3hot\n");
337 return 0;
340 static int hypercall_resume(struct pci_dev *pdev)
342 pci_restore_state(pdev);
343 pci_set_power_state(pdev, PCI_D0);
344 DPRINTK("Power mgmt resume, set power state to PCI_D0\n");
346 return 0;
349 #endif /* CONFIG_PM */
351 static void hypercall_cleanup_dev(struct hypercall_dev *dev)
353 DPRINTK("cleaning up\n");
354 pci_release_regions(dev->pci_dev);
355 pci_iounmap(dev->pci_dev, (void*)dev->io_addr);
356 pci_set_drvdata (dev->pci_dev, NULL);
357 kfree(dev);
360 static struct pci_driver hypercall_pci_driver = {
361 .name = HYPERCALL_DRIVER_NAME,
362 .id_table = hypercall_pci_tbl,
363 .probe = hypercall_init_one,
364 .remove = __devexit_p(hypercall_remove_one),
365 #ifdef CONFIG_PM
366 .suspend = hypercall_suspend,
367 .resume = hypercall_resume,
368 #endif /* CONFIG_PM */
371 static int __init hypercall_init_module(void)
373 printk (KERN_INFO HYPERCALL_DRIVER_NAME "\n");
374 return pci_module_init(&hypercall_pci_driver);
377 static void __exit hypercall_cleanup_module(void)
379 pci_unregister_driver(&hypercall_pci_driver);
383 * sysfs support
386 struct hypercall_attribute {
387 struct attribute attr;
388 ssize_t (*show)(struct hypercall_dev*, char *buf);
389 ssize_t (*store)(struct hypercall_dev*, unsigned long val);
392 static ssize_t hypercall_attribute_show(struct kobject *kobj,
393 struct attribute *attr, char *buf)
395 struct hypercall_attribute *hypercall_attr;
396 struct hypercall_dev *hdev;
398 hypercall_attr = container_of(attr, struct hypercall_attribute, attr);
399 hdev = container_of(kobj, struct hypercall_dev, kobject);
401 if (!hypercall_attr->show)
402 return -EIO;
404 return hypercall_attr->show(hdev, buf);
407 static ssize_t hypercall_attribute_store(struct kobject *kobj,
408 struct attribute *attr, const char *buf, size_t count)
410 struct hypercall_attribute *hypercall_attr;
411 struct hypercall_dev *hdev;
412 char *endp;
413 unsigned long val;
414 int rc;
416 val = simple_strtoul(buf, &endp, 0);
418 hypercall_attr = container_of(attr, struct hypercall_attribute, attr);
419 hdev = container_of(kobj, struct hypercall_dev, kobject);
421 if (!hypercall_attr->store)
422 return -EIO;
424 rc = hypercall_attr->store(hdev, val);
425 if (!rc)
426 rc = count;
427 return rc;
430 #define MAKE_HYPERCALL_R_ATTR(_name) \
431 static ssize_t _name##_show(struct hypercall_dev *hdev, char *buf) \
433 return sprintf(buf, "%lu\n", (unsigned long)hdev->_name); \
435 struct hypercall_attribute hypercall_attr_##_name = __ATTR_RO(_name)
437 #define MAKE_HYPERCALL_WR_ATTR(_name) \
438 static int _name##_store(struct hypercall_dev *hdev, unsigned long val) \
440 hdev->_name = (typeof(hdev->_name))val; \
441 return 0; \
443 static ssize_t _name##_show(struct hypercall_dev *hdev, char *buf) \
445 return sprintf(buf, "%lu\n", (unsigned long)hdev->_name); \
447 struct hypercall_attribute hypercall_attr_##_name = \
448 __ATTR(_name,S_IRUGO|S_IWUGO,_name##_show,_name##_store)
450 MAKE_HYPERCALL_R_ATTR(base_addr);
451 MAKE_HYPERCALL_R_ATTR(irq);
452 MAKE_HYPERCALL_WR_ATTR(cmd);
454 #define GET_HYPERCALL_ATTR(_name) (&hypercall_attr_##_name.attr)
456 static struct attribute *hypercall_default_attrs[] = {
457 GET_HYPERCALL_ATTR(base_addr),
458 GET_HYPERCALL_ATTR(irq),
459 GET_HYPERCALL_ATTR(cmd),
460 NULL
463 static struct sysfs_ops hypercall_sysfs_ops = {
464 .show = hypercall_attribute_show,
465 .store = hypercall_attribute_store,
468 static void hypercall_sysfs_release(struct kobject *kobj)
470 DPRINTK(" called for obj name %s\n", kobj->name);
473 static struct kobj_type hypercall_ktype = {
474 .release = hypercall_sysfs_release,
475 .sysfs_ops = &hypercall_sysfs_ops,
476 .default_attrs = hypercall_default_attrs
480 static int hypercall_sysfs_add(struct hypercall_dev *dev)
482 int rc;
484 kobject_init(&dev->kobject);
485 dev->kobject.ktype = &hypercall_ktype;
486 rc = kobject_set_name(&dev->kobject, "%s", HYPERCALL_DRIVER_NAME);
487 if (rc != 0) {
488 printk("%s: kobject_set_name failed, err=%d\n", __FUNCTION__, rc);
489 return rc;
492 rc = kobject_add(&dev->kobject);
493 if (rc != 0) {
494 printk("%s: kobject_add failed, err=%d\n", __FUNCTION__, rc);
495 return rc;
498 rc = sysfs_create_link(&dev->pci_dev->dev.kobj, &dev->kobject,
499 HYPERCALL_DRIVER_NAME);
500 if (rc != 0) {
501 printk("%s: sysfs_create_link failed, err=%d\n", __FUNCTION__, rc);
502 kobject_del(&dev->kobject);
505 return rc;
508 static void hypercall_sysfs_remove(struct hypercall_dev *dev)
510 sysfs_remove_link(&dev->pci_dev->dev.kobj, HYPERCALL_DRIVER_NAME);
511 kobject_del(&dev->kobject);
514 module_init(hypercall_init_module);
515 module_exit(hypercall_cleanup_module);