18fbab3b6SPaul Durrant /* Copyright (c) Citrix Systems Inc. 28fbab3b6SPaul Durrant * All rights reserved. 38fbab3b6SPaul Durrant * 48fbab3b6SPaul Durrant * Redistribution and use in source and binary forms, 58fbab3b6SPaul Durrant * with or without modification, are permitted provided 68fbab3b6SPaul Durrant * that the following conditions are met: 78fbab3b6SPaul Durrant * 88fbab3b6SPaul Durrant * * Redistributions of source code must retain the above 98fbab3b6SPaul Durrant * copyright notice, this list of conditions and the 108fbab3b6SPaul Durrant * following disclaimer. 118fbab3b6SPaul Durrant * * Redistributions in binary form must reproduce the above 128fbab3b6SPaul Durrant * copyright notice, this list of conditions and the 138fbab3b6SPaul Durrant * following disclaimer in the documentation and/or other 148fbab3b6SPaul Durrant * materials provided with the distribution. 158fbab3b6SPaul Durrant * 168fbab3b6SPaul Durrant * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 178fbab3b6SPaul Durrant * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 188fbab3b6SPaul Durrant * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 198fbab3b6SPaul Durrant * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 208fbab3b6SPaul Durrant * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 218fbab3b6SPaul Durrant * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 228fbab3b6SPaul Durrant * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 238fbab3b6SPaul Durrant * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 248fbab3b6SPaul Durrant * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 258fbab3b6SPaul Durrant * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 268fbab3b6SPaul Durrant * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 278fbab3b6SPaul Durrant * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 288fbab3b6SPaul Durrant * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 298fbab3b6SPaul Durrant * SUCH DAMAGE. 308fbab3b6SPaul Durrant */ 318fbab3b6SPaul Durrant 32b6a0aa05SPeter Maydell #include "qemu/osdep.h" 33da34e65cSMarkus Armbruster #include "qapi/error.h" 340b8fa32fSMarkus Armbruster #include "qemu/module.h" 35edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h" 36a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 37d6454270SMarkus Armbruster #include "migration/vmstate.h" 388fbab3b6SPaul Durrant #include "trace.h" 39db1015e9SEduardo Habkost #include "qom/object.h" 408fbab3b6SPaul Durrant 418fbab3b6SPaul Durrant #define TYPE_XEN_PV_DEVICE "xen-pvdevice" 428fbab3b6SPaul Durrant 438063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(XenPVDevice, XEN_PV_DEVICE) 448fbab3b6SPaul Durrant 45db1015e9SEduardo Habkost struct XenPVDevice { 468fbab3b6SPaul Durrant /*< private >*/ 478fbab3b6SPaul Durrant PCIDevice parent_obj; 488fbab3b6SPaul Durrant /*< public >*/ 498fbab3b6SPaul Durrant uint16_t vendor_id; 508fbab3b6SPaul Durrant uint16_t device_id; 518fbab3b6SPaul Durrant uint8_t revision; 528fbab3b6SPaul Durrant uint32_t size; 538fbab3b6SPaul Durrant MemoryRegion mmio; 54db1015e9SEduardo Habkost }; 558fbab3b6SPaul Durrant 568fbab3b6SPaul Durrant static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr, 578fbab3b6SPaul Durrant unsigned size) 588fbab3b6SPaul Durrant { 598fbab3b6SPaul Durrant trace_xen_pv_mmio_read(addr); 608fbab3b6SPaul Durrant 618fbab3b6SPaul Durrant return ~(uint64_t)0; 628fbab3b6SPaul Durrant } 638fbab3b6SPaul Durrant 648fbab3b6SPaul Durrant static void xen_pv_mmio_write(void *opaque, hwaddr addr, 658fbab3b6SPaul Durrant uint64_t val, unsigned size) 668fbab3b6SPaul Durrant { 678fbab3b6SPaul Durrant trace_xen_pv_mmio_write(addr); 688fbab3b6SPaul Durrant } 698fbab3b6SPaul Durrant 708fbab3b6SPaul Durrant static const MemoryRegionOps xen_pv_mmio_ops = { 718fbab3b6SPaul Durrant .read = &xen_pv_mmio_read, 728fbab3b6SPaul Durrant .write = &xen_pv_mmio_write, 738fbab3b6SPaul Durrant .endianness = DEVICE_LITTLE_ENDIAN, 748fbab3b6SPaul Durrant }; 758fbab3b6SPaul Durrant 761dd6af73SIgor Druzhinin static const VMStateDescription vmstate_xen_pvdevice = { 771dd6af73SIgor Druzhinin .name = "xen-pvdevice", 781dd6af73SIgor Druzhinin .version_id = 1, 791dd6af73SIgor Druzhinin .minimum_version_id = 1, 809231a017SRichard Henderson .fields = (const VMStateField[]) { 811dd6af73SIgor Druzhinin VMSTATE_PCI_DEVICE(parent_obj, XenPVDevice), 821dd6af73SIgor Druzhinin VMSTATE_END_OF_LIST() 831dd6af73SIgor Druzhinin } 841dd6af73SIgor Druzhinin }; 851dd6af73SIgor Druzhinin 86c6b14aedSCao jin static void xen_pv_realize(PCIDevice *pci_dev, Error **errp) 878fbab3b6SPaul Durrant { 888fbab3b6SPaul Durrant XenPVDevice *d = XEN_PV_DEVICE(pci_dev); 898fbab3b6SPaul Durrant uint8_t *pci_conf; 908fbab3b6SPaul Durrant 91539891a8SPaul Durrant /* device-id property must always be supplied */ 92c6b14aedSCao jin if (d->device_id == 0xffff) { 93c6b14aedSCao jin error_setg(errp, "Device ID invalid, it must always be supplied"); 94c6b14aedSCao jin return; 95c6b14aedSCao jin } 96539891a8SPaul Durrant 978fbab3b6SPaul Durrant pci_conf = pci_dev->config; 988fbab3b6SPaul Durrant 998fbab3b6SPaul Durrant pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id); 1008fbab3b6SPaul Durrant pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id); 1018fbab3b6SPaul Durrant pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id); 1028fbab3b6SPaul Durrant pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id); 1038fbab3b6SPaul Durrant pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision); 1048fbab3b6SPaul Durrant 1058fbab3b6SPaul Durrant pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY); 1068fbab3b6SPaul Durrant 1078fbab3b6SPaul Durrant pci_config_set_prog_interface(pci_conf, 0); 1088fbab3b6SPaul Durrant 1098fbab3b6SPaul Durrant pci_conf[PCI_INTERRUPT_PIN] = 1; 1108fbab3b6SPaul Durrant 1118fbab3b6SPaul Durrant memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d, 1128fbab3b6SPaul Durrant "mmio", d->size); 1138fbab3b6SPaul Durrant 1148fbab3b6SPaul Durrant pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, 1158fbab3b6SPaul Durrant &d->mmio); 1168fbab3b6SPaul Durrant } 1178fbab3b6SPaul Durrant 118*90d45638SRichard Henderson static const Property xen_pv_props[] = { 1198fbab3b6SPaul Durrant DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN), 120539891a8SPaul Durrant DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff), 1218fbab3b6SPaul Durrant DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01), 1228fbab3b6SPaul Durrant DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000), 1238fbab3b6SPaul Durrant DEFINE_PROP_END_OF_LIST() 1248fbab3b6SPaul Durrant }; 1258fbab3b6SPaul Durrant 1268fbab3b6SPaul Durrant static void xen_pv_class_init(ObjectClass *klass, void *data) 1278fbab3b6SPaul Durrant { 1288fbab3b6SPaul Durrant DeviceClass *dc = DEVICE_CLASS(klass); 1298fbab3b6SPaul Durrant PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1308fbab3b6SPaul Durrant 131c6b14aedSCao jin k->realize = xen_pv_realize; 1328fbab3b6SPaul Durrant k->class_id = PCI_CLASS_SYSTEM_OTHER; 1338fbab3b6SPaul Durrant dc->desc = "Xen PV Device"; 1344f67d30bSMarc-André Lureau device_class_set_props(dc, xen_pv_props); 1351dd6af73SIgor Druzhinin dc->vmsd = &vmstate_xen_pvdevice; 1368fbab3b6SPaul Durrant } 1378fbab3b6SPaul Durrant 1388fbab3b6SPaul Durrant static const TypeInfo xen_pv_type_info = { 1398fbab3b6SPaul Durrant .name = TYPE_XEN_PV_DEVICE, 1408fbab3b6SPaul Durrant .parent = TYPE_PCI_DEVICE, 1418fbab3b6SPaul Durrant .instance_size = sizeof(XenPVDevice), 1428fbab3b6SPaul Durrant .class_init = xen_pv_class_init, 143fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) { 144fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 145fd3b02c8SEduardo Habkost { }, 146fd3b02c8SEduardo Habkost }, 1478fbab3b6SPaul Durrant }; 1488fbab3b6SPaul Durrant 1498fbab3b6SPaul Durrant static void xen_pv_register_types(void) 1508fbab3b6SPaul Durrant { 1518fbab3b6SPaul Durrant type_register_static(&xen_pv_type_info); 1528fbab3b6SPaul Durrant } 1538fbab3b6SPaul Durrant 1548fbab3b6SPaul Durrant type_init(xen_pv_register_types) 155