iPXE
virtio-pci.c
Go to the documentation of this file.
00001 /* virtio-pci.c - pci interface for virtio interface
00002  *
00003  * (c) Copyright 2008 Bull S.A.S.
00004  *
00005  *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
00006  *
00007  * some parts from Linux Virtio PCI driver
00008  *
00009  *  Copyright IBM Corp. 2007
00010  *  Authors: Anthony Liguori  <aliguori@us.ibm.com>
00011  *
00012  */
00013 
00014 #include "errno.h"
00015 #include "byteswap.h"
00016 #include "etherboot.h"
00017 #include "ipxe/io.h"
00018 #include "ipxe/iomap.h"
00019 #include "ipxe/pci.h"
00020 #include "ipxe/reboot.h"
00021 #include "ipxe/virtio-pci.h"
00022 #include "ipxe/virtio-ring.h"
00023 
00024 static int vp_alloc_vq(struct vring_virtqueue *vq, u16 num)
00025 {
00026     size_t queue_size = PAGE_MASK + vring_size(num);
00027     size_t vdata_size = num * sizeof(void *);
00028 
00029     vq->queue = zalloc(queue_size + vdata_size);
00030     if (!vq->queue) {
00031         return -ENOMEM;
00032     }
00033 
00034     /* vdata immediately follows the ring */
00035     vq->vdata = (void **)(vq->queue + queue_size);
00036 
00037     return 0;
00038 }
00039 
00040 void vp_free_vq(struct vring_virtqueue *vq)
00041 {
00042     if (vq->queue) {
00043         free(vq->queue);
00044         vq->queue = NULL;
00045         vq->vdata = NULL;
00046     }
00047 }
00048 
00049 int vp_find_vq(unsigned int ioaddr, int queue_index,
00050                struct vring_virtqueue *vq)
00051 {
00052    struct vring * vr = &vq->vring;
00053    u16 num;
00054    int rc;
00055 
00056    /* select the queue */
00057 
00058    outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
00059 
00060    /* check if the queue is available */
00061 
00062    num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
00063    if (!num) {
00064            DBG("VIRTIO-PCI ERROR: queue size is 0\n");
00065            return -1;
00066    }
00067 
00068    /* check if the queue is already active */
00069 
00070    if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
00071            DBG("VIRTIO-PCI ERROR: queue already active\n");
00072            return -1;
00073    }
00074 
00075    vq->queue_index = queue_index;
00076 
00077    /* initialize the queue */
00078    rc = vp_alloc_vq(vq, num);
00079    if (rc) {
00080            DBG("VIRTIO-PCI ERROR: failed to allocate queue memory\n");
00081            return rc;
00082    }
00083    vring_init(vr, num, vq->queue);
00084 
00085    /* activate the queue
00086     *
00087     * NOTE: vr->desc is initialized by vring_init()
00088     */
00089 
00090    outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
00091         ioaddr + VIRTIO_PCI_QUEUE_PFN);
00092 
00093    return num;
00094 }
00095 
00096 #define CFG_POS(vdev, field) \
00097     (vdev->cfg_cap_pos + offsetof(struct virtio_pci_cfg_cap, field))
00098 
00099 static void prep_pci_cfg_cap(struct virtio_pci_modern_device *vdev,
00100                              struct virtio_pci_region *region,
00101                              size_t offset, u32 length)
00102 {
00103     pci_write_config_byte(vdev->pci, CFG_POS(vdev, cap.bar), region->bar);
00104     pci_write_config_dword(vdev->pci, CFG_POS(vdev, cap.length), length);
00105     pci_write_config_dword(vdev->pci, CFG_POS(vdev, cap.offset),
00106         (intptr_t)(region->base + offset));
00107 }
00108 
00109 void vpm_iowrite8(struct virtio_pci_modern_device *vdev,
00110                   struct virtio_pci_region *region, u8 data, size_t offset)
00111 {
00112     switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
00113     case VIRTIO_PCI_REGION_MEMORY:
00114         writeb(data, region->base + offset);
00115         break;
00116     case VIRTIO_PCI_REGION_PORT:
00117         outb(data, region->base + offset);
00118         break;
00119     case VIRTIO_PCI_REGION_PCI_CONFIG:
00120         prep_pci_cfg_cap(vdev, region, offset, 1);
00121         pci_write_config_byte(vdev->pci, CFG_POS(vdev, pci_cfg_data), data);
00122         break;
00123     default:
00124         assert(0);
00125         break;
00126     }
00127 }
00128 
00129 void vpm_iowrite16(struct virtio_pci_modern_device *vdev,
00130                    struct virtio_pci_region *region, u16 data, size_t offset)
00131 {
00132     data = cpu_to_le16(data);
00133     switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
00134     case VIRTIO_PCI_REGION_MEMORY:
00135         writew(data, region->base + offset);
00136         break;
00137     case VIRTIO_PCI_REGION_PORT:
00138         outw(data, region->base + offset);
00139         break;
00140     case VIRTIO_PCI_REGION_PCI_CONFIG:
00141         prep_pci_cfg_cap(vdev, region, offset, 2);
00142         pci_write_config_word(vdev->pci, CFG_POS(vdev, pci_cfg_data), data);
00143         break;
00144     default:
00145         assert(0);
00146         break;
00147     }
00148 }
00149 
00150 void vpm_iowrite32(struct virtio_pci_modern_device *vdev,
00151                    struct virtio_pci_region *region, u32 data, size_t offset)
00152 {
00153     data = cpu_to_le32(data);
00154     switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
00155     case VIRTIO_PCI_REGION_MEMORY:
00156         writel(data, region->base + offset);
00157         break;
00158     case VIRTIO_PCI_REGION_PORT:
00159         outl(data, region->base + offset);
00160         break;
00161     case VIRTIO_PCI_REGION_PCI_CONFIG:
00162         prep_pci_cfg_cap(vdev, region, offset, 4);
00163         pci_write_config_dword(vdev->pci, CFG_POS(vdev, pci_cfg_data), data);
00164         break;
00165     default:
00166         assert(0);
00167         break;
00168     }
00169 }
00170 
00171 u8 vpm_ioread8(struct virtio_pci_modern_device *vdev,
00172                struct virtio_pci_region *region, size_t offset)
00173 {
00174     uint8_t data;
00175     switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
00176     case VIRTIO_PCI_REGION_MEMORY:
00177         data = readb(region->base + offset);
00178         break;
00179     case VIRTIO_PCI_REGION_PORT:
00180         data = inb(region->base + offset);
00181         break;
00182     case VIRTIO_PCI_REGION_PCI_CONFIG:
00183         prep_pci_cfg_cap(vdev, region, offset, 1);
00184         pci_read_config_byte(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data);
00185         break;
00186     default:
00187         assert(0);
00188         data = 0;
00189         break;
00190     }
00191     return data;
00192 }
00193 
00194 u16 vpm_ioread16(struct virtio_pci_modern_device *vdev,
00195                  struct virtio_pci_region *region, size_t offset)
00196 {
00197     uint16_t data;
00198     switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
00199     case VIRTIO_PCI_REGION_MEMORY:
00200         data = readw(region->base + offset);
00201         break;
00202     case VIRTIO_PCI_REGION_PORT:
00203         data = inw(region->base + offset);
00204         break;
00205     case VIRTIO_PCI_REGION_PCI_CONFIG:
00206         prep_pci_cfg_cap(vdev, region, offset, 2);
00207         pci_read_config_word(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data);
00208         break;
00209     default:
00210         assert(0);
00211         data = 0;
00212         break;
00213     }
00214     return le16_to_cpu(data);
00215 }
00216 
00217 u32 vpm_ioread32(struct virtio_pci_modern_device *vdev,
00218                  struct virtio_pci_region *region, size_t offset)
00219 {
00220     uint32_t data;
00221     switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
00222     case VIRTIO_PCI_REGION_MEMORY:
00223         data = readw(region->base + offset);
00224         break;
00225     case VIRTIO_PCI_REGION_PORT:
00226         data = inw(region->base + offset);
00227         break;
00228     case VIRTIO_PCI_REGION_PCI_CONFIG:
00229         prep_pci_cfg_cap(vdev, region, offset, 4);
00230         pci_read_config_dword(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data);
00231         break;
00232     default:
00233         assert(0);
00234         data = 0;
00235         break;
00236     }
00237     return le32_to_cpu(data);
00238 }
00239 
00240 int virtio_pci_find_capability(struct pci_device *pci, uint8_t cfg_type)
00241 {
00242     int pos;
00243     uint8_t type, bar;
00244 
00245     for (pos = pci_find_capability(pci, PCI_CAP_ID_VNDR);
00246          pos > 0;
00247          pos = pci_find_next_capability(pci, pos, PCI_CAP_ID_VNDR)) {
00248 
00249         pci_read_config_byte(pci, pos + offsetof(struct virtio_pci_cap,
00250             cfg_type), &type);
00251         pci_read_config_byte(pci, pos + offsetof(struct virtio_pci_cap,
00252             bar), &bar);
00253 
00254         /* Ignore structures with reserved BAR values */
00255         if (bar > 0x5) {
00256             continue;
00257         }
00258 
00259         if (type == cfg_type) {
00260             return pos;
00261         }
00262     }
00263     return 0;
00264 }
00265 
00266 int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen,
00267                               u32 align, u32 start, u32 size,
00268                               struct virtio_pci_region *region)
00269 {
00270     u8 bar;
00271     u32 offset, length, base_raw;
00272     unsigned long base;
00273 
00274     pci_read_config_byte(pci, cap + offsetof(struct virtio_pci_cap, bar), &bar);
00275     pci_read_config_dword(pci, cap + offsetof(struct virtio_pci_cap, offset),
00276                           &offset);
00277     pci_read_config_dword(pci, cap + offsetof(struct virtio_pci_cap, length),
00278                           &length);
00279 
00280     if (length <= start) {
00281         DBG("VIRTIO-PCI bad capability len %d (>%d expected)\n", length, start);
00282         return -EINVAL;
00283     }
00284     if (length - start < minlen) {
00285         DBG("VIRTIO-PCI bad capability len %d (>=%zd expected)\n", length, minlen);
00286         return -EINVAL;
00287     }
00288     length -= start;
00289     if (start + offset < offset) {
00290         DBG("VIRTIO-PCI map wrap-around %d+%d\n", start, offset);
00291         return -EINVAL;
00292     }
00293     offset += start;
00294     if (offset & (align - 1)) {
00295         DBG("VIRTIO-PCI offset %d not aligned to %d\n", offset, align);
00296         return -EINVAL;
00297     }
00298     if (length > size) {
00299         length = size;
00300     }
00301 
00302     if (minlen + offset < minlen ||
00303         minlen + offset > pci_bar_size(pci, PCI_BASE_ADDRESS(bar))) {
00304         DBG("VIRTIO-PCI map virtio %zd@%d out of range on bar %i length %ld\n",
00305             minlen, offset,
00306             bar, pci_bar_size(pci, PCI_BASE_ADDRESS(bar)));
00307         return -EINVAL;
00308     }
00309 
00310     region->base = NULL;
00311     region->length = length;
00312     region->bar = bar;
00313 
00314     base = pci_bar_start(pci, PCI_BASE_ADDRESS(bar));
00315     if (base) {
00316         pci_read_config_dword(pci, PCI_BASE_ADDRESS(bar), &base_raw);
00317 
00318         if (base_raw & PCI_BASE_ADDRESS_SPACE_IO) {
00319             /* Region accessed using port I/O */
00320             region->base = (void *)(base + offset);
00321             region->flags = VIRTIO_PCI_REGION_PORT;
00322         } else {
00323             /* Region mapped into memory space */
00324             region->base = ioremap(base + offset, length);
00325             region->flags = VIRTIO_PCI_REGION_MEMORY;
00326         }
00327     }
00328     if (!region->base) {
00329         /* Region accessed via PCI config space window */
00330             region->base = (void *)(intptr_t)offset;
00331         region->flags = VIRTIO_PCI_REGION_PCI_CONFIG;
00332     }
00333     return 0;
00334 }
00335 
00336 void virtio_pci_unmap_capability(struct virtio_pci_region *region)
00337 {
00338     unsigned region_type = region->flags & VIRTIO_PCI_REGION_TYPE_MASK;
00339     if (region_type == VIRTIO_PCI_REGION_MEMORY) {
00340         iounmap(region->base);
00341     }
00342 }
00343 
00344 void vpm_notify(struct virtio_pci_modern_device *vdev,
00345                 struct vring_virtqueue *vq)
00346 {
00347     vpm_iowrite16(vdev, &vq->notification, (u16)vq->queue_index, 0);
00348 }
00349 
00350 int vpm_find_vqs(struct virtio_pci_modern_device *vdev,
00351                  unsigned nvqs, struct vring_virtqueue *vqs)
00352 {
00353     unsigned i;
00354     struct vring_virtqueue *vq;
00355     u16 size, off;
00356     u32 notify_offset_multiplier;
00357     int err;
00358 
00359     if (nvqs > vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(num_queues))) {
00360         return -ENOENT;
00361     }
00362 
00363     /* Read notify_off_multiplier from config space. */
00364     pci_read_config_dword(vdev->pci,
00365         vdev->notify_cap_pos + offsetof(struct virtio_pci_notify_cap,
00366         notify_off_multiplier),
00367         &notify_offset_multiplier);
00368 
00369     for (i = 0; i < nvqs; i++) {
00370         /* Select the queue we're interested in */
00371         vpm_iowrite16(vdev, &vdev->common, (u16)i, COMMON_OFFSET(queue_select));
00372 
00373         /* Check if queue is either not available or already active. */
00374         size = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_size));
00375         /* QEMU has a bug where queues don't revert to inactive on device
00376          * reset. Skip checking the queue_enable field until it is fixed.
00377          */
00378         if (!size /*|| vpm_ioread16(vdev, &vdev->common.queue_enable)*/)
00379             return -ENOENT;
00380 
00381         if (size & (size - 1)) {
00382             DBG("VIRTIO-PCI %p: bad queue size %d\n", vdev, size);
00383             return -EINVAL;
00384         }
00385 
00386         if (size > MAX_QUEUE_NUM) {
00387             /* iPXE networking tends to be not perf critical so there's no
00388              * need to accept large queue sizes.
00389              */
00390             size = MAX_QUEUE_NUM;
00391         }
00392 
00393         vq = &vqs[i];
00394         vq->queue_index = i;
00395 
00396         /* get offset of notification word for this vq */
00397         off = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_notify_off));
00398 
00399         err = vp_alloc_vq(vq, size);
00400         if (err) {
00401             DBG("VIRTIO-PCI %p: failed to allocate queue memory\n", vdev);
00402             return err;
00403         }
00404         vring_init(&vq->vring, size, vq->queue);
00405 
00406         /* activate the queue */
00407         vpm_iowrite16(vdev, &vdev->common, size, COMMON_OFFSET(queue_size));
00408 
00409         vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.desc),
00410                       COMMON_OFFSET(queue_desc_lo),
00411                       COMMON_OFFSET(queue_desc_hi));
00412         vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.avail),
00413                       COMMON_OFFSET(queue_avail_lo),
00414                       COMMON_OFFSET(queue_avail_hi));
00415         vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.used),
00416                       COMMON_OFFSET(queue_used_lo),
00417                       COMMON_OFFSET(queue_used_hi));
00418 
00419         err = virtio_pci_map_capability(vdev->pci,
00420             vdev->notify_cap_pos, 2, 2,
00421             off * notify_offset_multiplier, 2,
00422             &vq->notification);
00423         if (err) {
00424             return err;
00425         }
00426     }
00427 
00428     /* Select and activate all queues. Has to be done last: once we do
00429      * this, there's no way to go back except reset.
00430      */
00431     for (i = 0; i < nvqs; i++) {
00432         vq = &vqs[i];
00433         vpm_iowrite16(vdev, &vdev->common, (u16)vq->queue_index,
00434                       COMMON_OFFSET(queue_select));
00435         vpm_iowrite16(vdev, &vdev->common, 1, COMMON_OFFSET(queue_enable));
00436     }
00437     return 0;
00438 }