1 /* Copyright (c) Citrix Systems Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, 5 * with or without modification, are permitted provided 6 * that the following conditions are met: 7 * 8 * * Redistributions of source code must retain the above 9 * copyright notice, this list of conditions and the 10 * following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the 13 * following disclaimer in the documentation and/or other 14 * materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 17 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include "qemu/osdep.h" 33 #include "qapi/error.h" 34 #include "qemu/module.h" 35 #include "hw/pci/pci.h" 36 #include "hw/qdev-properties.h" 37 #include "migration/vmstate.h" 38 #include "trace.h" 39 #include "qom/object.h" 40 41 #define TYPE_XEN_PV_DEVICE "xen-pvdevice" 42 43 typedef struct XenPVDevice XenPVDevice; 44 DECLARE_INSTANCE_CHECKER(XenPVDevice, XEN_PV_DEVICE, 45 TYPE_XEN_PV_DEVICE) 46 47 struct XenPVDevice { 48 /*< private >*/ 49 PCIDevice parent_obj; 50 /*< public >*/ 51 uint16_t vendor_id; 52 uint16_t device_id; 53 uint8_t revision; 54 uint32_t size; 55 MemoryRegion mmio; 56 }; 57 58 static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr, 59 unsigned size) 60 { 61 trace_xen_pv_mmio_read(addr); 62 63 return ~(uint64_t)0; 64 } 65 66 static void xen_pv_mmio_write(void *opaque, hwaddr addr, 67 uint64_t val, unsigned size) 68 { 69 trace_xen_pv_mmio_write(addr); 70 } 71 72 static const MemoryRegionOps xen_pv_mmio_ops = { 73 .read = &xen_pv_mmio_read, 74 .write = &xen_pv_mmio_write, 75 .endianness = DEVICE_LITTLE_ENDIAN, 76 }; 77 78 static const VMStateDescription vmstate_xen_pvdevice = { 79 .name = "xen-pvdevice", 80 .version_id = 1, 81 .minimum_version_id = 1, 82 .fields = (VMStateField[]) { 83 VMSTATE_PCI_DEVICE(parent_obj, XenPVDevice), 84 VMSTATE_END_OF_LIST() 85 } 86 }; 87 88 static void xen_pv_realize(PCIDevice *pci_dev, Error **errp) 89 { 90 XenPVDevice *d = XEN_PV_DEVICE(pci_dev); 91 uint8_t *pci_conf; 92 93 /* device-id property must always be supplied */ 94 if (d->device_id == 0xffff) { 95 error_setg(errp, "Device ID invalid, it must always be supplied"); 96 return; 97 } 98 99 pci_conf = pci_dev->config; 100 101 pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id); 102 pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id); 103 pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id); 104 pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id); 105 pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision); 106 107 pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY); 108 109 pci_config_set_prog_interface(pci_conf, 0); 110 111 pci_conf[PCI_INTERRUPT_PIN] = 1; 112 113 memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d, 114 "mmio", d->size); 115 116 pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, 117 &d->mmio); 118 } 119 120 static Property xen_pv_props[] = { 121 DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN), 122 DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff), 123 DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01), 124 DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000), 125 DEFINE_PROP_END_OF_LIST() 126 }; 127 128 static void xen_pv_class_init(ObjectClass *klass, void *data) 129 { 130 DeviceClass *dc = DEVICE_CLASS(klass); 131 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 132 133 k->realize = xen_pv_realize; 134 k->class_id = PCI_CLASS_SYSTEM_OTHER; 135 dc->desc = "Xen PV Device"; 136 device_class_set_props(dc, xen_pv_props); 137 dc->vmsd = &vmstate_xen_pvdevice; 138 } 139 140 static const TypeInfo xen_pv_type_info = { 141 .name = TYPE_XEN_PV_DEVICE, 142 .parent = TYPE_PCI_DEVICE, 143 .instance_size = sizeof(XenPVDevice), 144 .class_init = xen_pv_class_init, 145 .interfaces = (InterfaceInfo[]) { 146 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 147 { }, 148 }, 149 }; 150 151 static void xen_pv_register_types(void) 152 { 153 type_register_static(&xen_pv_type_info); 154 } 155 156 type_init(xen_pv_register_types) 157