1*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio-pci.h" 2*b0d56e3cSJean-Philippe Brucker 3*b0d56e3cSJean-Philippe Brucker #include "kvm/ioport.h" 4*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio.h" 5*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio-pci-dev.h" 6*b0d56e3cSJean-Philippe Brucker 7*b0d56e3cSJean-Philippe Brucker #include <linux/virtio_config.h> 8*b0d56e3cSJean-Philippe Brucker 9*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_COMMON_SIZE sizeof(struct virtio_pci_common_cfg) 10*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_COMMON_START 0 11*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_COMMON_END (VPCI_CFG_COMMON_SIZE - 1) 12*b0d56e3cSJean-Philippe Brucker /* 13*b0d56e3cSJean-Philippe Brucker * Use a naturally aligned 4-byte doorbell, in case we ever want to 14*b0d56e3cSJean-Philippe Brucker * implement VIRTIO_F_NOTIFICATION_DATA 15*b0d56e3cSJean-Philippe Brucker */ 16*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_NOTIFY_SIZE 4 17*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_NOTIFY_START (VPCI_CFG_COMMON_END + 1) 18*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_NOTIFY_END (VPCI_CFG_COMMON_END + VPCI_CFG_NOTIFY_SIZE) 19*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_ISR_SIZE 4 20*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_ISR_START (VPCI_CFG_NOTIFY_END + 1) 21*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_ISR_END (VPCI_CFG_NOTIFY_END + VPCI_CFG_ISR_SIZE) 22*b0d56e3cSJean-Philippe Brucker /* 23*b0d56e3cSJean-Philippe Brucker * We're at 64 bytes. Use the remaining 192 bytes in PCI_IO_SIZE for the 24*b0d56e3cSJean-Philippe Brucker * device-specific config space. It's sufficient for the devices we 25*b0d56e3cSJean-Philippe Brucker * currently implement (virtio_blk_config is 60 bytes) and, I think, all 26*b0d56e3cSJean-Philippe Brucker * existing virtio 1.2 devices. 27*b0d56e3cSJean-Philippe Brucker */ 28*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_DEV_START (VPCI_CFG_ISR_END + 1) 29*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_DEV_END ((PCI_IO_SIZE) - 1) 30*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_DEV_SIZE (VPCI_CFG_DEV_END - VPCI_CFG_DEV_START + 1) 31*b0d56e3cSJean-Philippe Brucker 32*b0d56e3cSJean-Philippe Brucker #define vpci_selected_vq(vpci) \ 33*b0d56e3cSJean-Philippe Brucker vdev->ops->get_vq((vpci)->kvm, (vpci)->dev, (vpci)->queue_selector) 34*b0d56e3cSJean-Philippe Brucker 35*b0d56e3cSJean-Philippe Brucker typedef bool (*access_handler_t)(struct virtio_device *, unsigned long, void *, int); 36*b0d56e3cSJean-Philippe Brucker 37*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__common_write(struct virtio_device *vdev, 38*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size) 39*b0d56e3cSJean-Philippe Brucker { 40*b0d56e3cSJean-Philippe Brucker u64 features; 41*b0d56e3cSJean-Philippe Brucker u32 val, gsi, vec; 42*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 43*b0d56e3cSJean-Philippe Brucker 44*b0d56e3cSJean-Philippe Brucker switch (offset - VPCI_CFG_COMMON_START) { 45*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_DFSELECT: 46*b0d56e3cSJean-Philippe Brucker vpci->device_features_sel = ioport__read32(data); 47*b0d56e3cSJean-Philippe Brucker break; 48*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_GFSELECT: 49*b0d56e3cSJean-Philippe Brucker vpci->driver_features_sel = ioport__read32(data); 50*b0d56e3cSJean-Philippe Brucker break; 51*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_GF: 52*b0d56e3cSJean-Philippe Brucker val = ioport__read32(data); 53*b0d56e3cSJean-Philippe Brucker if (vpci->driver_features_sel > 1) 54*b0d56e3cSJean-Philippe Brucker break; 55*b0d56e3cSJean-Philippe Brucker 56*b0d56e3cSJean-Philippe Brucker features = (u64)val << (32 * vpci->driver_features_sel); 57*b0d56e3cSJean-Philippe Brucker virtio_set_guest_features(vpci->kvm, vdev, vpci->dev, features); 58*b0d56e3cSJean-Philippe Brucker break; 59*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_MSIX: 60*b0d56e3cSJean-Philippe Brucker vec = vpci->config_vector = ioport__read16(data); 61*b0d56e3cSJean-Philippe Brucker gsi = virtio_pci__add_msix_route(vpci, vec); 62*b0d56e3cSJean-Philippe Brucker if (gsi < 0) 63*b0d56e3cSJean-Philippe Brucker break; 64*b0d56e3cSJean-Philippe Brucker 65*b0d56e3cSJean-Philippe Brucker vpci->config_gsi = gsi; 66*b0d56e3cSJean-Philippe Brucker break; 67*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_STATUS: 68*b0d56e3cSJean-Philippe Brucker vpci->status = ioport__read8(data); 69*b0d56e3cSJean-Philippe Brucker virtio_notify_status(vpci->kvm, vdev, vpci->dev, vpci->status); 70*b0d56e3cSJean-Philippe Brucker break; 71*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_SELECT: 72*b0d56e3cSJean-Philippe Brucker val = ioport__read16(data); 73*b0d56e3cSJean-Philippe Brucker if (val >= (u32)vdev->ops->get_vq_count(vpci->kvm, vpci->dev)) 74*b0d56e3cSJean-Philippe Brucker pr_warning("invalid vq number %u", val); 75*b0d56e3cSJean-Philippe Brucker else 76*b0d56e3cSJean-Philippe Brucker vpci->queue_selector = val; 77*b0d56e3cSJean-Philippe Brucker break; 78*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_SIZE: 79*b0d56e3cSJean-Philippe Brucker vdev->ops->set_size_vq(vpci->kvm, vpci->dev, 80*b0d56e3cSJean-Philippe Brucker vpci->queue_selector, 81*b0d56e3cSJean-Philippe Brucker ioport__read16(data)); 82*b0d56e3cSJean-Philippe Brucker break; 83*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_MSIX: 84*b0d56e3cSJean-Philippe Brucker vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data); 85*b0d56e3cSJean-Philippe Brucker 86*b0d56e3cSJean-Philippe Brucker gsi = virtio_pci__add_msix_route(vpci, vec); 87*b0d56e3cSJean-Philippe Brucker if (gsi < 0) 88*b0d56e3cSJean-Philippe Brucker break; 89*b0d56e3cSJean-Philippe Brucker 90*b0d56e3cSJean-Philippe Brucker vpci->gsis[vpci->queue_selector] = gsi; 91*b0d56e3cSJean-Philippe Brucker if (vdev->ops->notify_vq_gsi) 92*b0d56e3cSJean-Philippe Brucker vdev->ops->notify_vq_gsi(vpci->kvm, vpci->dev, 93*b0d56e3cSJean-Philippe Brucker vpci->queue_selector, gsi); 94*b0d56e3cSJean-Philippe Brucker break; 95*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_ENABLE: 96*b0d56e3cSJean-Philippe Brucker val = ioport__read16(data); 97*b0d56e3cSJean-Philippe Brucker if (val) 98*b0d56e3cSJean-Philippe Brucker virtio_pci_init_vq(vpci->kvm, vdev, vpci->queue_selector); 99*b0d56e3cSJean-Philippe Brucker else 100*b0d56e3cSJean-Philippe Brucker virtio_pci_exit_vq(vpci->kvm, vdev, vpci->queue_selector); 101*b0d56e3cSJean-Philippe Brucker break; 102*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_DESCLO: 103*b0d56e3cSJean-Philippe Brucker vpci_selected_vq(vpci)->vring_addr.desc_lo = ioport__read32(data); 104*b0d56e3cSJean-Philippe Brucker break; 105*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_DESCHI: 106*b0d56e3cSJean-Philippe Brucker vpci_selected_vq(vpci)->vring_addr.desc_hi = ioport__read32(data); 107*b0d56e3cSJean-Philippe Brucker break; 108*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_AVAILLO: 109*b0d56e3cSJean-Philippe Brucker vpci_selected_vq(vpci)->vring_addr.avail_lo = ioport__read32(data); 110*b0d56e3cSJean-Philippe Brucker break; 111*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_AVAILHI: 112*b0d56e3cSJean-Philippe Brucker vpci_selected_vq(vpci)->vring_addr.avail_hi = ioport__read32(data); 113*b0d56e3cSJean-Philippe Brucker break; 114*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_USEDLO: 115*b0d56e3cSJean-Philippe Brucker vpci_selected_vq(vpci)->vring_addr.used_lo = ioport__read32(data); 116*b0d56e3cSJean-Philippe Brucker break; 117*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_USEDHI: 118*b0d56e3cSJean-Philippe Brucker vpci_selected_vq(vpci)->vring_addr.used_hi = ioport__read32(data); 119*b0d56e3cSJean-Philippe Brucker break; 120*b0d56e3cSJean-Philippe Brucker } 121*b0d56e3cSJean-Philippe Brucker 122*b0d56e3cSJean-Philippe Brucker return true; 123*b0d56e3cSJean-Philippe Brucker } 124*b0d56e3cSJean-Philippe Brucker 125*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__notify_write(struct virtio_device *vdev, 126*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size) 127*b0d56e3cSJean-Philippe Brucker { 128*b0d56e3cSJean-Philippe Brucker u16 vq = ioport__read16(data); 129*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 130*b0d56e3cSJean-Philippe Brucker 131*b0d56e3cSJean-Philippe Brucker vdev->ops->notify_vq(vpci->kvm, vpci->dev, vq); 132*b0d56e3cSJean-Philippe Brucker 133*b0d56e3cSJean-Philippe Brucker return true; 134*b0d56e3cSJean-Philippe Brucker } 135*b0d56e3cSJean-Philippe Brucker 136*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__config_write(struct virtio_device *vdev, 137*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size) 138*b0d56e3cSJean-Philippe Brucker { 139*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 140*b0d56e3cSJean-Philippe Brucker 141*b0d56e3cSJean-Philippe Brucker return virtio_access_config(vpci->kvm, vdev, vpci->dev, 142*b0d56e3cSJean-Philippe Brucker offset - VPCI_CFG_DEV_START, data, size, 143*b0d56e3cSJean-Philippe Brucker true); 144*b0d56e3cSJean-Philippe Brucker } 145*b0d56e3cSJean-Philippe Brucker 146*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__common_read(struct virtio_device *vdev, 147*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size) 148*b0d56e3cSJean-Philippe Brucker { 149*b0d56e3cSJean-Philippe Brucker u32 val; 150*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 151*b0d56e3cSJean-Philippe Brucker u64 features = 1ULL << VIRTIO_F_VERSION_1; 152*b0d56e3cSJean-Philippe Brucker 153*b0d56e3cSJean-Philippe Brucker switch (offset - VPCI_CFG_COMMON_START) { 154*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_DFSELECT: 155*b0d56e3cSJean-Philippe Brucker val = vpci->device_features_sel; 156*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 157*b0d56e3cSJean-Philippe Brucker break; 158*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_DF: 159*b0d56e3cSJean-Philippe Brucker if (vpci->device_features_sel > 1) 160*b0d56e3cSJean-Philippe Brucker break; 161*b0d56e3cSJean-Philippe Brucker features |= vdev->ops->get_host_features(vpci->kvm, vpci->dev); 162*b0d56e3cSJean-Philippe Brucker val = features >> (32 * vpci->device_features_sel); 163*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 164*b0d56e3cSJean-Philippe Brucker break; 165*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_GFSELECT: 166*b0d56e3cSJean-Philippe Brucker val = vpci->driver_features_sel; 167*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 168*b0d56e3cSJean-Philippe Brucker break; 169*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_MSIX: 170*b0d56e3cSJean-Philippe Brucker val = vpci->config_vector; 171*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 172*b0d56e3cSJean-Philippe Brucker break; 173*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_NUMQ: 174*b0d56e3cSJean-Philippe Brucker val = vdev->ops->get_vq_count(vpci->kvm, vpci->dev); 175*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 176*b0d56e3cSJean-Philippe Brucker break; 177*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_STATUS: 178*b0d56e3cSJean-Philippe Brucker ioport__write8(data, vpci->status); 179*b0d56e3cSJean-Philippe Brucker break; 180*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_CFGGENERATION: 181*b0d56e3cSJean-Philippe Brucker /* 182*b0d56e3cSJean-Philippe Brucker * The config generation changes when the device updates a 183*b0d56e3cSJean-Philippe Brucker * config field larger than 32 bits, that the driver may read 184*b0d56e3cSJean-Philippe Brucker * using multiple accesses. Since kvmtool doesn't use any 185*b0d56e3cSJean-Philippe Brucker * mutable config field larger than 32 bits, the generation is 186*b0d56e3cSJean-Philippe Brucker * constant. 187*b0d56e3cSJean-Philippe Brucker */ 188*b0d56e3cSJean-Philippe Brucker ioport__write8(data, 0); 189*b0d56e3cSJean-Philippe Brucker break; 190*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_SELECT: 191*b0d56e3cSJean-Philippe Brucker ioport__write16(data, vpci->queue_selector); 192*b0d56e3cSJean-Philippe Brucker break; 193*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_SIZE: 194*b0d56e3cSJean-Philippe Brucker val = vdev->ops->get_size_vq(vpci->kvm, vpci->dev, 195*b0d56e3cSJean-Philippe Brucker vpci->queue_selector); 196*b0d56e3cSJean-Philippe Brucker ioport__write16(data, val); 197*b0d56e3cSJean-Philippe Brucker break; 198*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_MSIX: 199*b0d56e3cSJean-Philippe Brucker val = vpci->vq_vector[vpci->queue_selector]; 200*b0d56e3cSJean-Philippe Brucker ioport__write16(data, val); 201*b0d56e3cSJean-Philippe Brucker break; 202*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_ENABLE: 203*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->enabled; 204*b0d56e3cSJean-Philippe Brucker ioport__write16(data, val); 205*b0d56e3cSJean-Philippe Brucker break; 206*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_NOFF: 207*b0d56e3cSJean-Philippe Brucker val = vpci->queue_selector; 208*b0d56e3cSJean-Philippe Brucker ioport__write16(data, val); 209*b0d56e3cSJean-Philippe Brucker break; 210*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_DESCLO: 211*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->vring_addr.desc_lo; 212*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 213*b0d56e3cSJean-Philippe Brucker break; 214*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_DESCHI: 215*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->vring_addr.desc_hi; 216*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 217*b0d56e3cSJean-Philippe Brucker break; 218*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_AVAILLO: 219*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->vring_addr.avail_lo; 220*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 221*b0d56e3cSJean-Philippe Brucker break; 222*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_AVAILHI: 223*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->vring_addr.avail_hi; 224*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 225*b0d56e3cSJean-Philippe Brucker break; 226*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_USEDLO: 227*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->vring_addr.used_lo; 228*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 229*b0d56e3cSJean-Philippe Brucker break; 230*b0d56e3cSJean-Philippe Brucker case VIRTIO_PCI_COMMON_Q_USEDHI: 231*b0d56e3cSJean-Philippe Brucker val = vpci_selected_vq(vpci)->vring_addr.used_hi; 232*b0d56e3cSJean-Philippe Brucker ioport__write32(data, val); 233*b0d56e3cSJean-Philippe Brucker break; 234*b0d56e3cSJean-Philippe Brucker }; 235*b0d56e3cSJean-Philippe Brucker 236*b0d56e3cSJean-Philippe Brucker return true; 237*b0d56e3cSJean-Philippe Brucker } 238*b0d56e3cSJean-Philippe Brucker 239*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__isr_read(struct virtio_device *vdev, 240*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size) 241*b0d56e3cSJean-Philippe Brucker { 242*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 243*b0d56e3cSJean-Philippe Brucker 244*b0d56e3cSJean-Philippe Brucker if (WARN_ON(offset - VPCI_CFG_ISR_START != 0)) 245*b0d56e3cSJean-Philippe Brucker return false; 246*b0d56e3cSJean-Philippe Brucker 247*b0d56e3cSJean-Philippe Brucker ioport__write8(data, vpci->isr); 248*b0d56e3cSJean-Philippe Brucker /* 249*b0d56e3cSJean-Philippe Brucker * Interrupts are edge triggered (yes, going against the PCI and virtio 250*b0d56e3cSJean-Philippe Brucker * specs), so no need to deassert the IRQ line. 251*b0d56e3cSJean-Philippe Brucker */ 252*b0d56e3cSJean-Philippe Brucker vpci->isr = 0; 253*b0d56e3cSJean-Philippe Brucker 254*b0d56e3cSJean-Philippe Brucker return 0; 255*b0d56e3cSJean-Philippe Brucker } 256*b0d56e3cSJean-Philippe Brucker 257*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__config_read(struct virtio_device *vdev, 258*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size) 259*b0d56e3cSJean-Philippe Brucker { 260*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 261*b0d56e3cSJean-Philippe Brucker 262*b0d56e3cSJean-Philippe Brucker return virtio_access_config(vpci->kvm, vdev, vpci->dev, 263*b0d56e3cSJean-Philippe Brucker offset - VPCI_CFG_DEV_START, data, size, 264*b0d56e3cSJean-Philippe Brucker false); 265*b0d56e3cSJean-Philippe Brucker } 266*b0d56e3cSJean-Philippe Brucker 267*b0d56e3cSJean-Philippe Brucker static bool virtio_pci_access(struct kvm_cpu *vcpu, struct virtio_device *vdev, 268*b0d56e3cSJean-Philippe Brucker unsigned long offset, void *data, int size, 269*b0d56e3cSJean-Philippe Brucker bool write) 270*b0d56e3cSJean-Philippe Brucker { 271*b0d56e3cSJean-Philippe Brucker access_handler_t handler = NULL; 272*b0d56e3cSJean-Philippe Brucker 273*b0d56e3cSJean-Philippe Brucker switch (offset) { 274*b0d56e3cSJean-Philippe Brucker case VPCI_CFG_COMMON_START...VPCI_CFG_COMMON_END: 275*b0d56e3cSJean-Philippe Brucker if (write) 276*b0d56e3cSJean-Philippe Brucker handler = virtio_pci__common_write; 277*b0d56e3cSJean-Philippe Brucker else 278*b0d56e3cSJean-Philippe Brucker handler = virtio_pci__common_read; 279*b0d56e3cSJean-Philippe Brucker break; 280*b0d56e3cSJean-Philippe Brucker case VPCI_CFG_NOTIFY_START...VPCI_CFG_NOTIFY_END: 281*b0d56e3cSJean-Philippe Brucker if (write) 282*b0d56e3cSJean-Philippe Brucker handler = virtio_pci__notify_write; 283*b0d56e3cSJean-Philippe Brucker break; 284*b0d56e3cSJean-Philippe Brucker case VPCI_CFG_ISR_START...VPCI_CFG_ISR_END: 285*b0d56e3cSJean-Philippe Brucker if (!write) 286*b0d56e3cSJean-Philippe Brucker handler = virtio_pci__isr_read; 287*b0d56e3cSJean-Philippe Brucker break; 288*b0d56e3cSJean-Philippe Brucker case VPCI_CFG_DEV_START...VPCI_CFG_DEV_END: 289*b0d56e3cSJean-Philippe Brucker if (write) 290*b0d56e3cSJean-Philippe Brucker handler = virtio_pci__config_write; 291*b0d56e3cSJean-Philippe Brucker else 292*b0d56e3cSJean-Philippe Brucker handler = virtio_pci__config_read; 293*b0d56e3cSJean-Philippe Brucker break; 294*b0d56e3cSJean-Philippe Brucker } 295*b0d56e3cSJean-Philippe Brucker 296*b0d56e3cSJean-Philippe Brucker if (!handler) 297*b0d56e3cSJean-Philippe Brucker return false; 298*b0d56e3cSJean-Philippe Brucker 299*b0d56e3cSJean-Philippe Brucker return handler(vdev, offset, data, size); 300*b0d56e3cSJean-Philippe Brucker } 301*b0d56e3cSJean-Philippe Brucker 302*b0d56e3cSJean-Philippe Brucker void virtio_pci_modern__io_mmio_callback(struct kvm_cpu *vcpu, u64 addr, 303*b0d56e3cSJean-Philippe Brucker u8 *data, u32 len, u8 is_write, 304*b0d56e3cSJean-Philippe Brucker void *ptr) 305*b0d56e3cSJean-Philippe Brucker { 306*b0d56e3cSJean-Philippe Brucker struct virtio_device *vdev = ptr; 307*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 308*b0d56e3cSJean-Philippe Brucker u32 mmio_addr = virtio_pci__mmio_addr(vpci); 309*b0d56e3cSJean-Philippe Brucker 310*b0d56e3cSJean-Philippe Brucker virtio_pci_access(vcpu, vdev, addr - mmio_addr, data, len, is_write); 311*b0d56e3cSJean-Philippe Brucker } 312*b0d56e3cSJean-Philippe Brucker 313*b0d56e3cSJean-Philippe Brucker int virtio_pci_modern_init(struct virtio_device *vdev) 314*b0d56e3cSJean-Philippe Brucker { 315*b0d56e3cSJean-Philippe Brucker int subsys_id; 316*b0d56e3cSJean-Philippe Brucker struct virtio_pci *vpci = vdev->virtio; 317*b0d56e3cSJean-Philippe Brucker struct pci_device_header *hdr = &vpci->pci_hdr; 318*b0d56e3cSJean-Philippe Brucker 319*b0d56e3cSJean-Philippe Brucker subsys_id = le16_to_cpu(hdr->subsys_id); 320*b0d56e3cSJean-Philippe Brucker 321*b0d56e3cSJean-Philippe Brucker hdr->device_id = cpu_to_le16(PCI_DEVICE_ID_VIRTIO_BASE + subsys_id); 322*b0d56e3cSJean-Philippe Brucker hdr->subsys_id = cpu_to_le16(PCI_SUBSYS_ID_VIRTIO_BASE + subsys_id); 323*b0d56e3cSJean-Philippe Brucker 324*b0d56e3cSJean-Philippe Brucker vpci->doorbell_offset = VPCI_CFG_NOTIFY_START; 325*b0d56e3cSJean-Philippe Brucker vdev->endian = VIRTIO_ENDIAN_LE; 326*b0d56e3cSJean-Philippe Brucker 327*b0d56e3cSJean-Philippe Brucker hdr->msix.next = PCI_CAP_OFF(hdr, virtio); 328*b0d56e3cSJean-Philippe Brucker 329*b0d56e3cSJean-Philippe Brucker hdr->virtio.common = (struct virtio_pci_cap) { 330*b0d56e3cSJean-Philippe Brucker .cap_vndr = PCI_CAP_ID_VNDR, 331*b0d56e3cSJean-Philippe Brucker .cap_next = PCI_CAP_OFF(hdr, virtio.notify), 332*b0d56e3cSJean-Philippe Brucker .cap_len = sizeof(hdr->virtio.common), 333*b0d56e3cSJean-Philippe Brucker .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG, 334*b0d56e3cSJean-Philippe Brucker .bar = 1, 335*b0d56e3cSJean-Philippe Brucker .offset = cpu_to_le32(VPCI_CFG_COMMON_START), 336*b0d56e3cSJean-Philippe Brucker .length = cpu_to_le32(VPCI_CFG_COMMON_SIZE), 337*b0d56e3cSJean-Philippe Brucker }; 338*b0d56e3cSJean-Philippe Brucker BUILD_BUG_ON(VPCI_CFG_COMMON_START & 0x3); 339*b0d56e3cSJean-Philippe Brucker 340*b0d56e3cSJean-Philippe Brucker hdr->virtio.notify = (struct virtio_pci_notify_cap) { 341*b0d56e3cSJean-Philippe Brucker .cap.cap_vndr = PCI_CAP_ID_VNDR, 342*b0d56e3cSJean-Philippe Brucker .cap.cap_next = PCI_CAP_OFF(hdr, virtio.isr), 343*b0d56e3cSJean-Philippe Brucker .cap.cap_len = sizeof(hdr->virtio.notify), 344*b0d56e3cSJean-Philippe Brucker .cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG, 345*b0d56e3cSJean-Philippe Brucker .cap.bar = 1, 346*b0d56e3cSJean-Philippe Brucker .cap.offset = cpu_to_le32(VPCI_CFG_NOTIFY_START), 347*b0d56e3cSJean-Philippe Brucker .cap.length = cpu_to_le32(VPCI_CFG_NOTIFY_SIZE), 348*b0d56e3cSJean-Philippe Brucker /* 349*b0d56e3cSJean-Philippe Brucker * Notify multiplier is 0, meaning that notifications are all on 350*b0d56e3cSJean-Philippe Brucker * the same register 351*b0d56e3cSJean-Philippe Brucker */ 352*b0d56e3cSJean-Philippe Brucker }; 353*b0d56e3cSJean-Philippe Brucker BUILD_BUG_ON(VPCI_CFG_NOTIFY_START & 0x3); 354*b0d56e3cSJean-Philippe Brucker 355*b0d56e3cSJean-Philippe Brucker hdr->virtio.isr = (struct virtio_pci_cap) { 356*b0d56e3cSJean-Philippe Brucker .cap_vndr = PCI_CAP_ID_VNDR, 357*b0d56e3cSJean-Philippe Brucker .cap_next = PCI_CAP_OFF(hdr, virtio.device), 358*b0d56e3cSJean-Philippe Brucker .cap_len = sizeof(hdr->virtio.isr), 359*b0d56e3cSJean-Philippe Brucker .cfg_type = VIRTIO_PCI_CAP_ISR_CFG, 360*b0d56e3cSJean-Philippe Brucker .bar = 1, 361*b0d56e3cSJean-Philippe Brucker .offset = cpu_to_le32(VPCI_CFG_ISR_START), 362*b0d56e3cSJean-Philippe Brucker .length = cpu_to_le32(VPCI_CFG_ISR_SIZE), 363*b0d56e3cSJean-Philippe Brucker }; 364*b0d56e3cSJean-Philippe Brucker 365*b0d56e3cSJean-Philippe Brucker hdr->virtio.device = (struct virtio_pci_cap) { 366*b0d56e3cSJean-Philippe Brucker .cap_vndr = PCI_CAP_ID_VNDR, 367*b0d56e3cSJean-Philippe Brucker .cap_next = PCI_CAP_OFF(hdr, virtio.pci), 368*b0d56e3cSJean-Philippe Brucker .cap_len = sizeof(hdr->virtio.device), 369*b0d56e3cSJean-Philippe Brucker .cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG, 370*b0d56e3cSJean-Philippe Brucker .bar = 1, 371*b0d56e3cSJean-Philippe Brucker .offset = cpu_to_le32(VPCI_CFG_DEV_START), 372*b0d56e3cSJean-Philippe Brucker .length = cpu_to_le32(VPCI_CFG_DEV_SIZE), 373*b0d56e3cSJean-Philippe Brucker }; 374*b0d56e3cSJean-Philippe Brucker BUILD_BUG_ON(VPCI_CFG_DEV_START & 0x3); 375*b0d56e3cSJean-Philippe Brucker 376*b0d56e3cSJean-Philippe Brucker /* 377*b0d56e3cSJean-Philippe Brucker * TODO: implement this weird proxy capability (it is a "MUST" in the 378*b0d56e3cSJean-Philippe Brucker * spec, but I don't know if anyone actually uses it). 379*b0d56e3cSJean-Philippe Brucker * It doesn't use any BAR space. Instead the driver writes .cap.offset 380*b0d56e3cSJean-Philippe Brucker * and .cap.length to access a register in a BAR. 381*b0d56e3cSJean-Philippe Brucker */ 382*b0d56e3cSJean-Philippe Brucker hdr->virtio.pci = (struct virtio_pci_cfg_cap) { 383*b0d56e3cSJean-Philippe Brucker .cap.cap_vndr = PCI_CAP_ID_VNDR, 384*b0d56e3cSJean-Philippe Brucker .cap.cap_next = 0, 385*b0d56e3cSJean-Philippe Brucker .cap.cap_len = sizeof(hdr->virtio.pci), 386*b0d56e3cSJean-Philippe Brucker .cap.cfg_type = VIRTIO_PCI_CAP_PCI_CFG, 387*b0d56e3cSJean-Philippe Brucker }; 388*b0d56e3cSJean-Philippe Brucker 389*b0d56e3cSJean-Philippe Brucker return 0; 390*b0d56e3cSJean-Philippe Brucker } 391