diff options
-rw-r--r-- | board-qemu/slof/virtio-block.fs | 10 | ||||
-rw-r--r-- | include/helpers.h | 5 | ||||
-rw-r--r-- | lib/libusb/tools.h | 5 | ||||
-rw-r--r-- | lib/libvirtio/virtio-blk.c | 34 | ||||
-rw-r--r-- | lib/libvirtio/virtio-blk.h | 10 | ||||
-rw-r--r-- | lib/libvirtio/virtio.c | 13 | ||||
-rw-r--r-- | lib/libvirtio/virtio.code | 6 | ||||
-rw-r--r-- | lib/libvirtio/virtio.h | 1 |
8 files changed, 59 insertions, 25 deletions
diff --git a/board-qemu/slof/virtio-block.fs b/board-qemu/slof/virtio-block.fs index dc432b6..ea388fb 100644 --- a/board-qemu/slof/virtio-block.fs +++ b/board-qemu/slof/virtio-block.fs @@ -18,7 +18,7 @@ FALSE VALUE initialized? \ Required interface for deblocker -200 CONSTANT block-size +200 VALUE block-size 8000 CONSTANT max-transfer INSTANCE VARIABLE deblocker @@ -40,7 +40,7 @@ virtiodev virtio-setup-vd \ Basic device initialization - which has only to be done once : init ( -- ) - virtiodev virtio-blk-init + virtiodev virtio-blk-init to block-size TRUE to initialized? ['] shutdown add-quiesce-xt ; @@ -53,14 +53,14 @@ virtiodev virtio-setup-vd \ Standard node "open" function : open ( -- okay? ) open 0= IF false EXIT THEN + dup initialized? 0= AND IF + init + THEN 0 0 s" deblocker" $open-package dup deblocker ! dup IF s" disk-label" find-package IF my-args rot interpose THEN THEN - dup initialized? 0= AND IF - init - THEN 0<> ; diff --git a/include/helpers.h b/include/helpers.h index 1663ea8..f6d4375 100644 --- a/include/helpers.h +++ b/include/helpers.h @@ -34,4 +34,9 @@ extern void SLOF_pci_config_write32(long offset, long value); extern void SLOF_pci_config_write16(long offset, long value); extern void *SLOF_translate_my_address(void *addr); +#define offset_of(type, member) ((long) &((type *)0)->member) +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member)* struct_ptr = (ptr); \ + (type *)((char *)struct_ptr - offset_of(type, member)); }) + #endif diff --git a/lib/libusb/tools.h b/lib/libusb/tools.h index 497a1a0..f531175 100644 --- a/lib/libusb/tools.h +++ b/lib/libusb/tools.h @@ -74,9 +74,4 @@ static inline void ci_write_reg(uint32_t *reg, uint32_t value) ci_write_32(reg, bswap_32(value)); } -#define offset_of(type, member) ((long) &((type *)0)->member) -#define container_of(ptr, type, member) ({ \ - const typeof(((type *)0)->member)* struct_ptr = (ptr); \ - (type *)((char *)struct_ptr - offset_of(type, member)); }) - #endif diff --git a/lib/libvirtio/virtio-blk.c b/lib/libvirtio/virtio-blk.c index 544068f..826f2ea 100644 --- a/lib/libvirtio/virtio-blk.c +++ b/lib/libvirtio/virtio-blk.c @@ -16,6 +16,8 @@ #include "virtio.h" #include "virtio-blk.h" +#define DEFAULT_SECTOR_SIZE 512 + /** * Initialize virtio-block device. * @param dev pointer to virtio device information @@ -24,6 +26,8 @@ int virtioblk_init(struct virtio_device *dev) { struct vring_avail *vq_avail; + int blk_size = DEFAULT_SECTOR_SIZE; + int features; /* Reset device */ // XXX That will clear the virtq base. We need to move @@ -37,8 +41,8 @@ virtioblk_init(struct virtio_device *dev) /* Tell HV that we know how to drive the device. */ virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER); - /* Device specific setup - we do not support special features right now */ - virtio_set_guest_features(dev, 0); + /* Device specific setup - we support F_BLK_SIZE */ + virtio_set_guest_features(dev, VIRTIO_BLK_F_BLK_SIZE); vq_avail = virtio_get_vring_avail(dev, 0); vq_avail->flags = VRING_AVAIL_F_NO_INTERRUPT; @@ -48,7 +52,14 @@ virtioblk_init(struct virtio_device *dev) virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER |VIRTIO_STAT_DRIVER_OK); - return 0; + virtio_get_host_features(dev, &features); + if (features & VIRTIO_BLK_F_BLK_SIZE) { + blk_size = virtio_get_config(dev, + offset_of(struct virtio_blk_cfg, blk_size), + sizeof(blk_size)); + } + + return blk_size; } @@ -90,17 +101,28 @@ virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt) volatile uint8_t status = -1; volatile uint16_t *current_used_idx; uint16_t last_used_idx; + int blk_size = DEFAULT_SECTOR_SIZE; //printf("virtioblk_read: dev=%p buf=%p blocknum=%li count=%li\n", // dev, buf, blocknum, cnt); /* Check whether request is within disk capacity */ - capacity = virtio_get_config(dev, 0, sizeof(capacity)); + capacity = virtio_get_config(dev, + offset_of(struct virtio_blk_cfg, capacity), + sizeof(capacity)); if (blocknum + cnt - 1 > capacity) { puts("virtioblk_read: Access beyond end of device!"); return 0; } + blk_size = virtio_get_config(dev, + offset_of(struct virtio_blk_cfg, blk_size), + sizeof(blk_size)); + if (blk_size % DEFAULT_SECTOR_SIZE) { + fprintf(stderr, "virtio-blk: Unaligned sector read %d\n", blk_size); + return 0; + } + vq_size = virtio_get_qsize(dev, 0); vq_desc = virtio_get_vring_desc(dev, 0); vq_avail = virtio_get_vring_avail(dev, 0); @@ -112,7 +134,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt) /* Set up header */ blkhdr.type = VIRTIO_BLK_T_IN | VIRTIO_BLK_T_BARRIER; blkhdr.ioprio = 1; - blkhdr.sector = blocknum; + blkhdr.sector = blocknum * blk_size / DEFAULT_SECTOR_SIZE; /* Determine descriptor index */ id = (vq_avail->idx * 3) % vq_size; @@ -127,7 +149,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt) /* Set up virtqueue descriptor for data */ desc = &vq_desc[(id + 1) % vq_size]; desc->addr = (uint64_t)buf; - desc->len = cnt * 512; + desc->len = cnt * blk_size; desc->flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE; desc->next = (id + 2) % vq_size; diff --git a/lib/libvirtio/virtio-blk.h b/lib/libvirtio/virtio-blk.h index 7c2b7e0..ac8bf28 100644 --- a/lib/libvirtio/virtio-blk.h +++ b/lib/libvirtio/virtio-blk.h @@ -21,9 +21,7 @@ #include <stdint.h> -/* Device configuration layout */ -/* -struct virtio_blk_config { +struct virtio_blk_cfg { uint64_t capacity; uint32_t size_max; uint32_t seg_max; @@ -34,8 +32,7 @@ struct virtio_blk_config { } geometry; uint32_t blk_size; uint32_t sectors_max; -}; -*/ +} __attribute__ ((packed)) ; /* Block request */ struct virtio_blk_req { @@ -53,6 +50,9 @@ struct virtio_blk_req { #define VIRTIO_BLK_T_FLUSH_OUT 5 #define VIRTIO_BLK_T_BARRIER 0x80000000 +/* VIRTIO_BLK Feature bits */ +#define VIRTIO_BLK_F_BLK_SIZE (1 << 6) + extern int virtioblk_init(struct virtio_device *dev); extern void virtioblk_shutdown(struct virtio_device *dev); extern int virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt); diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c index 249f803..b010796 100644 --- a/lib/libvirtio/virtio.c +++ b/lib/libvirtio/virtio.c @@ -162,7 +162,18 @@ void virtio_set_guest_features(struct virtio_device *dev, int features) { if (dev->type == VIRTIO_TYPE_PCI) { - ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, features); + ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, bswap_32(features)); + } +} + +/** + * Get host feature bits + */ +void virtio_get_host_features(struct virtio_device *dev, int *features) + +{ + if (dev->type == VIRTIO_TYPE_PCI && features) { + *features = bswap_32(ci_read_32(dev->base+VIRTIOHDR_DEVICE_FEATURES)); } } diff --git a/lib/libvirtio/virtio.code b/lib/libvirtio/virtio.code index 304849e..258b9bb 100644 --- a/lib/libvirtio/virtio.code +++ b/lib/libvirtio/virtio.code @@ -46,10 +46,10 @@ MIRP /******** virtio-blk ********/ -// : virtio-blk-init ( dev -- ) +// : virtio-blk-init ( dev -- blk-size) PRIM(virtio_X2d_blk_X2d_init) - void *dev = TOS.a; POP; - virtioblk_init(dev); + void *dev = TOS.a; + TOS.u = virtioblk_init(dev); MIRP // : virtio-blk-shutdown ( dev -- ) diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h index b351930..d5759b4 100644 --- a/lib/libvirtio/virtio.h +++ b/lib/libvirtio/virtio.h @@ -81,6 +81,7 @@ extern void virtio_queue_notify(struct virtio_device *dev, int queue); extern void virtio_set_status(struct virtio_device *dev, int status); extern void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr); extern void virtio_set_guest_features(struct virtio_device *dev, int features); +extern void virtio_get_host_features(struct virtio_device *dev, int *features); extern uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size); extern int __virtio_read_config(struct virtio_device *dev, void *dst, int offset, int len); |