命令block_resize $block_id $size(单位MB)
virtio_blk_resize
virtio_notify_config
virtio_notify_vector
virtio_pci_notify
msix_notify
msg = msix_get_message(dev, vector);
stl_le_phys(msg.address, msg.data);
stl_phys_internal
io_mem_write(mr, addr1, val, 4);
guest:
设备初始化时注册中断,对应的处理方法是vp_config_changed
err = request_irq(vp_dev->msix_entries[v].vector,
vp_config_changed, 0, vp_dev->msix_names[v],
vp_dev);
点击(此处)折叠或打开
-
static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
-
bool per_vq_vectors)
-
{
-
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-
const char *name = dev_name(&vp_dev->vdev.dev);
-
unsigned i, v;
-
int err = -ENOMEM;
-
-
vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries,
-
GFP_KERNEL);
-
if (!vp_dev->msix_entries)
-
goto error;
-
vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
-
GFP_KERNEL);
-
if (!vp_dev->msix_names)
-
goto error;
-
-
for (i = 0; i < nvectors; ++i)
-
vp_dev->msix_entries[i].entry = i;
-
-
/* pci_enable_msix returns positive if we can't get this many. */
-
err = pci_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries, nvectors);
-
if (err > 0)
-
err = -ENOSPC;
-
if (err)
-
goto error;
-
vp_dev->msix_vectors = nvectors;
-
vp_dev->msix_enabled = 1;
-
-
/* Set the vector used for configuration */
-
v = vp_dev->msix_used_vectors;
-
snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
-
"%s-config", name);
-
err = request_irq(vp_dev->msix_entries[v].vector,
-
vp_config_changed, 0, vp_dev->msix_names[v],
-
vp_dev);
-
if (err)
-
goto error;
-
++vp_dev->msix_used_vectors;
-
-
iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
-
/* Verify we had enough resources to assign the vector */
-
v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
-
if (v == VIRTIO_MSI_NO_VECTOR) {
-
err = -EBUSY;
-
goto error;
-
}
-
-
if (!per_vq_vectors) {
-
/* Shared vector for all VQs */
-
v = vp_dev->msix_used_vectors;
-
snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
-
"%s-virtqueues", name);
-
err = request_irq(vp_dev->msix_entries[v].vector,
-
vp_vring_interrupt, 0, vp_dev->msix_names[v],
-
vp_dev);
-
if (err)
-
goto error;
-
++vp_dev->msix_used_vectors;
-
}
-
return 0;
-
error:
-
vp_free_vectors(vdev);
-
return err;
-
}
-
-
处理中断
-
static irqreturn_t vp_config_changed(int irq, void *opaque)
-
{
-
struct virtio_pci_device *vp_dev = opaque;
-
struct virtio_driver *drv;
-
drv = container_of(vp_dev->vdev.dev.driver,
-
struct virtio_driver, driver);
-
-
if (drv && drv->config_changed)
-
drv->config_changed(&vp_dev->vdev);
-
return IRQ_HANDLED;
-
}
-
-
static void virtblk_config_changed_work(struct work_struct *work)
-
{
-
struct virtio_blk *vblk =
-
container_of(work, struct virtio_blk, config_work);
-
struct virtio_device *vdev = vblk->vdev;
-
struct request_queue *q = vblk->disk->queue;
-
char cap_str_2[10], cap_str_10[10];
-
u64 capacity, size;
-
-
mutex_lock(&vblk->config_lock);
-
if (!vblk->config_enable)
-
goto done;
-
-
/* Host must always specify the capacity. */
-
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
-
&capacity, sizeof(capacity));//vm退出到host
-
-
/* If capacity is too big, truncate with warning. */
-
if ((sector_t)capacity != capacity) {
-
dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n",
-
(unsigned long long)capacity);
-
capacity = (sector_t)-1;
-
}
-
-
size = capacity * queue_logical_block_size(q);
-
string_get_size(size, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
-
string_get_size(size, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));
-
-
dev_notice(&vdev->dev,
-
"new size: %llu %d-byte logical blocks (%s/%s)\n",
-
(unsigned long long)capacity,
-
queue_logical_block_size(q),
-
cap_str_10, cap_str_2);
-
-
set_capacity(vblk->disk, capacity);
-
revalidate_disk(vblk->disk);
-
done:
-
mutex_unlock(&vblk->config_lock);
-
}
-
-
host:
-
uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
-
{
-
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-
uint8_t val;
-
-
if (addr + sizeof(val) > vdev->config_len) {
-
return (uint32_t)-1;
-
}
-
-
k->get_config(vdev, vdev->config);//对应到virtio_blk_update_config
-
-
val = ldub_p(vdev->config + addr);
-
return val;
-
}
-
-
static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
-
{
-
VirtIOBlock *s = VIRTIO_BLK(vdev);
-
struct virtio_blk_config blkcfg;
-
uint64_t capacity;
-
int blk_size = s->conf->logical_block_size;
-
-
bdrv_get_geometry(s->bs, &capacity);
-
memset(&blkcfg, 0, sizeof(blkcfg));
-
stq_raw(&blkcfg.capacity, capacity);
-
stl_raw(&blkcfg.seg_max, 128 - 2);
-
stw_raw(&blkcfg.cylinders, s->conf->cyls);
-
stl_raw(&blkcfg.blk_size, blk_size);
-
stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
-
stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
-
blkcfg.heads = s->conf->heads;
-
/*
-
* We must ensure that the block device capacity is a multiple of
-
* the logical block size. If that is not the case, let's use
-
* sector_mask to adopt the geometry to have a correct picture.
-
* For those devices where the capacity is ok for the given geometry
-
* we don't touch the sector value of the geometry, since some devices
-
* (like s390 dasd) need a specific value. Here the capacity is already
-
* cyls*heads*secs*blk_size and the sector value is not block size
-
* divided by 512 - instead it is the amount of blk_size blocks
-
* per track (cylinder).
-
*/
-
if (bdrv_getlength(s->bs) / s->conf->heads / s->conf->secs % blk_size) {
-
blkcfg.sectors = s->conf->secs & ~s->sector_mask;
-
} else {
-
blkcfg.sectors = s->conf->secs;
-
}
-
blkcfg.size_max = 0;
-
blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
-
blkcfg.alignment_offset = 0;
-
blkcfg.wce = bdrv_enable_write_cache(s->bs);
-
memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
- }