int virtio_load(VirtIODevice *vdev, QEMUFile *f) { int num, i, ret; uint32_t features; uint32_t supported_features = vdev->binding->get_features(vdev->binding_opaque); if (vdev->binding->load_config) { ret = vdev->binding->load_config(vdev->binding_opaque, f); if (ret) return ret; } qemu_get_8s(f, &vdev->status); qemu_get_8s(f, &vdev->isr); qemu_get_be16s(f, &vdev->queue_sel); qemu_get_be32s(f, &features); if (features & ~supported_features) { fprintf(stderr, "Features 0x%x unsupported. Allowed features: 0x%x\n", features, supported_features); return -1; } vdev->guest_features = features; vdev->config_len = qemu_get_be32(f); qemu_get_buffer(f, vdev->config, vdev->config_len); num = qemu_get_be32(f); for (i = 0; i < num; i++) { vdev->vq[i].vring.num = qemu_get_be32(f); vdev->vq[i].pa = qemu_get_be64(f); qemu_get_be16s(f, &vdev->vq[i].last_avail_idx); if (vdev->vq[i].pa) { virtqueue_init(&vdev->vq[i]); } if (vdev->binding->load_queue) { ret = vdev->binding->load_queue(vdev->binding_opaque, i, f); if (ret) return ret; } } virtio_notify_vector(vdev, VIRTIO_NO_VECTOR); return 0; }
static void IpcTask (void * pvParameters) { unsigned int msg, *local_vq_buf; int ret; struct virtqueue_buf virtq_buf; virtqueue_init(); nvic_enable_irq(MAILBOX_IRQ); enable_mailbox_irq(); for (;;) { xQueueReceive(MboxQueue, &msg, portMAX_DELAY); trace_printf("msg from mailbox : "); trace_value(msg); switch(msg) { case RP_MBOX_ECHO_REQUEST : mailbox_send(M3_TO_HOST_MBX, RP_MBOX_ECHO_REPLY); break; case HOST_TO_M3_VRING : ret = virtqueue_get_avail_buf(&virtqueue_list[msg], &virtq_buf); /* make a local copy of the buffer */ local_vq_buf = pvPortMalloc(RP_MSG_BUF_SIZE); memcpy(local_vq_buf, virtq_buf.buf_ptr, RP_MSG_BUF_SIZE); virtqueue_add_used_buf(&virtqueue_list[msg], virtq_buf.head); /* dispatch to the service queue */ rpmsg_dispatch_msg(local_vq_buf); break; case M3_TO_HOST_VRING : trace_printf("kick on vq0, dropping it \n"); xSemaphoreGive(InitDoneSemaphore); break; } } vTaskDelete(NULL); }
static void IpcTask (void * pvParameters) { unsigned int msg, *local_vq_buf; int ret; struct virtqueue_buf virtq_buf; portTickType LastWake; trace_append("%s: starting task\n", __func__); /* Workaround * * We can't enable interrupts in U-Boot. Let's wait until Linux is booted * on CPU. Linux remoteproc framework sends a ping to IPU via mailbox when * its initialization is completed. This ping is a good indicator for IPU * that Linux and its remoteproc/rpmsg subsystems are up an running. */ while (1) { msg = mailbox_read(); if (msg == HOST_ECHO_REQUEST) { trace_append("%s: received echo request [0x%x] from CPU\n", __func__, msg); break; } trace_append("%s: host-to-m3 mailbox [0x%x]\n", __func__, msg); LastWake = xTaskGetTickCount(); vTaskDelayUntil(&LastWake, 5000); } virtqueue_init(); nvic_enable_irq(MAILBOX_IRQ); enable_mailbox_irq(); trace_append("%s: start main loop\n", __func__); for (;;) { xQueueReceive(MboxQueue, &msg, portMAX_DELAY); switch(msg) { case RP_MBOX_ECHO_REQUEST : mailbox_send(M3_TO_HOST_MBX, RP_MBOX_ECHO_REPLY); break; case HOST_TO_M3_VRING : ret = virtqueue_get_avail_buf(&virtqueue_list[msg], &virtq_buf); /* make a local copy of the buffer */ local_vq_buf = pvPortMalloc(RP_MSG_BUF_SIZE); memcpy(local_vq_buf, virtq_buf.buf_ptr, RP_MSG_BUF_SIZE); virtqueue_add_used_buf(&virtqueue_list[msg], virtq_buf.head); /* dispatch to the service queue */ rpmsg_dispatch_msg(local_vq_buf); break; case M3_TO_HOST_VRING : xSemaphoreGive(InitDoneSemaphore); break; default: trace_append("%s: unknown message\n", __func__); break; } } vTaskDelete(NULL); }
void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr) { vdev->vq[n].pa = addr; virtqueue_init(&vdev->vq[n]); }