sync code with last improvements from OpenBSD

This commit is contained in:
purplerain 2023-09-14 18:14:55 +00:00
parent 88c72e05f8
commit aec8820748
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
11 changed files with 313 additions and 390 deletions

View File

@ -1 +1 @@
# SecBSD 1.3-c7a8681: Sun Sep 10 00:00:00 UTC 2023 (Tezcatlipoca)
# SecBSD 1.3-88c72e05f8: Thu Sep 14 00:00:00 UTC 2023 (Tezcatlipoca)

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: bsd.port.mk.5,v 1.627 2023/09/12 08:54:04 jsg Exp $
.\" $OpenBSD: bsd.port.mk.5,v 1.628 2023/09/14 14:06:13 sthen Exp $
.\"
.\" Copyright (c) 2000-2008 Marc Espie
.\"
@ -24,7 +24,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: September 12 2023 $
.Dd $Mdocdate: September 14 2023 $
.Dt BSD.PORT.MK 5
.Os
.Sh NAME
@ -746,6 +746,10 @@ See
Generate and print the list of static and dynamic libraries present in the port.
See
.Xr pkg_create 1 .
.It Cm print-plist-all-libs
Iterate over
.Cm print-plist-libs
for all subpackages in a given port.
.It Cm print-plist-libs-with-depends
Like
.Cm print-plist-libs ,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: screen-write.c,v 1.220 2023/09/01 16:01:54 nicm Exp $ */
/* $OpenBSD: screen-write.c,v 1.221 2023/09/14 13:01:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -1742,6 +1742,7 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
if (ci->used == 0)
return;
ctx->flags &= ~SCREEN_WRITE_COMBINE;
before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
&wrapped);
@ -1792,8 +1793,6 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
u_int sx = screen_size_x(s);
int collect;
ctx->flags &= ~SCREEN_WRITE_COMBINE;
/*
* Don't need to check that the attributes and whatnot are still the
* same - input_parse will end the collection when anything that isn't
@ -1873,7 +1872,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
screen_write_collect_flush(ctx, 0, __func__);
gc = screen_write_combine(ctx, combine, &xx, &cx);
if (gc != NULL) {
cy = s->cy;
cx = s->cx; cy = s->cy;
screen_write_set_cursor(ctx, xx, s->cy);
screen_write_initctx(ctx, &ttyctx, 0);
ttyctx.cell = gc;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: crunchgen.c,v 1.26 2023/04/16 19:57:01 deraadt Exp $ */
/* $OpenBSD: crunchgen.c,v 1.27 2023/09/14 16:39:00 jca Exp $ */
/*
* Copyright (c) 1994 University of Maryland
@ -904,7 +904,7 @@ top_makefile_rules(FILE * outmk)
fprintf(outmk, "CFLAGS+=-fno-asynchronous-unwind-tables\n");
fprintf(outmk, "LDFLAGS+=$(NOPIE_LDFLAGS)\n");
fprintf(outmk, "STRIP?=strip\n");
fprintf(outmk, "LINK=$(LD) -dc -r ${LDFLAGS}\n");
fprintf(outmk, "LINK=$(LD) -d -r ${LDFLAGS}\n");
fprintf(outmk, "LIBS=");
for (l = libdirs; l != NULL; l = l->next)
fprintf(outmk, " -L%s", l->str);

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: radiusd.conf.5,v 1.17 2023/09/08 05:56:22 yasuoka Exp $
.\" $OpenBSD: radiusd.conf.5,v 1.18 2023/09/14 09:55:28 yasuoka Exp $
.\"
.\" Copyright (c) 2014 Esdenera Networks GmbH
.\" Copyright (c) 2014, 2023 Internet Initiative Japan Inc.
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 8 2023 $
.Dd $Mdocdate: September 14 2023 $
.Dt RADIUSD.CONF 5
.Os
.Sh NAME
@ -130,7 +130,8 @@ This configuration cannot be omitted.
.It Ic max-tries Ar number
Specify the maximum number of retransmissions for a server.
.Xr radiusd 8
will retransmit 2, 6, 14, 22, and 30 seconds after the first transmission.
will retransmit 2, 6, 14, 22, and 30 seconds after the first transmission
and subsequent retransmissions will occur every 8 seconds.
If the number of retransmissions per server reaches this value,
the current server is marked as
.Dq fail ,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pfe_filter.c,v 1.63 2023/06/30 12:16:00 sashan Exp $ */
/* $OpenBSD: pfe_filter.c,v 1.65 2023/09/14 09:54:31 yasuoka Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vioblk.c,v 1.7 2023/09/06 19:27:54 dv Exp $ */
/* $OpenBSD: vioblk.c,v 1.8 2023/09/14 15:25:43 dv Exp $ */
/*
* Copyright (c) 2023 Dave Voutila <dv@openbsd.org>
@ -37,13 +37,18 @@
extern char *__progname;
extern struct vmd_vm *current_vm;
struct iovec io_v[VIOBLK_QUEUE_SIZE];
static const char *disk_type(int);
static uint32_t handle_io_read(struct viodev_msg *, struct virtio_dev *,
int8_t *);
static int handle_io_write(struct viodev_msg *, struct virtio_dev *);
void vioblk_notify_rx(struct vioblk_dev *);
int vioblk_notifyq(struct vioblk_dev *);
static void vioblk_update_qs(struct vioblk_dev *);
static void vioblk_update_qa(struct vioblk_dev *);
static int vioblk_notifyq(struct vioblk_dev *);
static ssize_t vioblk_rw(struct vioblk_dev *, int, off_t,
struct vring_desc *, struct vring_desc **);
static void dev_dispatch_vm(int, short, void *);
static void handle_sync_io(int, short, void *);
@ -79,6 +84,9 @@ vioblk_main(int fd, int fd_vmm)
if (pledge("stdio vmm proc", NULL) == -1)
fatal("pledge");
/* Zero and initialize io work queue. */
memset(io_v, 0, nitems(io_v)*sizeof(io_v[0]));
/* Receive our virtio_dev, mostly preconfigured. */
memset(&dev, 0, sizeof(dev));
sz = atomicio(read, fd, &dev, sizeof(dev));
@ -96,9 +104,9 @@ vioblk_main(int fd, int fd_vmm)
vioblk = &dev.vioblk;
log_debug("%s: got viblk dev. num disk fds = %d, sync fd = %d, "
"async fd = %d, sz = %lld maxfer = %d, vmm fd = %d", __func__,
vioblk->ndisk_fd, dev.sync_fd, dev.async_fd, vioblk->sz,
vioblk->max_xfer, fd_vmm);
"async fd = %d, capacity = %lld seg_max = %u, vmm fd = %d",
__func__, vioblk->ndisk_fd, dev.sync_fd, dev.async_fd,
vioblk->capacity, vioblk->seg_max, fd_vmm);
/* Receive our vm information from the vm process. */
memset(&vm, 0, sizeof(vm));
@ -145,9 +153,9 @@ vioblk_main(int fd, int fd_vmm)
log_warnx("failed to init disk %s image", disk_type(type));
goto fail;
}
vioblk->sz = szp / 512;
log_debug("%s: initialized vioblk[%d] with %s image (sz=%lld)",
__func__, vioblk->idx, disk_type(type), vioblk->sz);
vioblk->capacity = szp / 512;
log_debug("%s: initialized vioblk[%d] with %s image (capacity=%lld)",
__func__, vioblk->idx, disk_type(type), vioblk->capacity);
/* If we're restoring hardware, reinitialize the virtqueue hva. */
if (vm.vm_state & VM_STATE_RECEIVED)
@ -240,7 +248,7 @@ vioblk_cmd_name(uint32_t type)
}
}
void
static void
vioblk_update_qa(struct vioblk_dev *dev)
{
struct virtio_vq_info *vq_info;
@ -259,7 +267,7 @@ vioblk_update_qa(struct vioblk_dev *dev)
vq_info->q_hva = hva;
}
void
static void
vioblk_update_qs(struct vioblk_dev *dev)
{
struct virtio_vq_info *vq_info;
@ -277,122 +285,26 @@ vioblk_update_qs(struct vioblk_dev *dev)
dev->cfg.queue_size = vq_info->qs;
}
static void
vioblk_free_info(struct ioinfo *info)
{
if (!info)
return;
free(info->buf);
free(info);
}
static struct ioinfo *
vioblk_start_read(struct vioblk_dev *dev, off_t sector, size_t sz)
{
struct ioinfo *info;
/* Limit to 64M for now */
if (sz > (1 << 26)) {
log_warnx("%s: read size exceeded 64M", __func__);
return (NULL);
}
info = calloc(1, sizeof(*info));
if (!info)
goto nomem;
info->buf = malloc(sz);
if (info->buf == NULL)
goto nomem;
info->len = sz;
info->offset = sector * VIRTIO_BLK_SECTOR_SIZE;
return info;
nomem:
free(info);
log_warn("malloc error vioblk read");
return (NULL);
}
static const uint8_t *
vioblk_finish_read(struct vioblk_dev *dev, struct ioinfo *info)
{
struct virtio_backing *file = &dev->file;
if (file == NULL || file->pread == NULL) {
log_warnx("%s: XXX null?!", __func__);
return NULL;
}
if (file->pread(file->p, info->buf, info->len, info->offset) != info->len) {
log_warn("vioblk read error");
return NULL;
}
return info->buf;
}
static struct ioinfo *
vioblk_start_write(struct vioblk_dev *dev, off_t sector,
paddr_t addr, size_t len)
{
struct ioinfo *info;
/* Limit to 64M for now */
if (len > (1 << 26)) {
log_warnx("%s: write size exceeded 64M", __func__);
return (NULL);
}
info = calloc(1, sizeof(*info));
if (!info)
goto nomem;
info->buf = malloc(len);
if (info->buf == NULL)
goto nomem;
info->len = len;
info->offset = sector * VIRTIO_BLK_SECTOR_SIZE;
if (read_mem(addr, info->buf, info->len)) {
vioblk_free_info(info);
return NULL;
}
return info;
nomem:
free(info);
log_warn("malloc error vioblk write");
return (NULL);
}
static int
vioblk_finish_write(struct vioblk_dev *dev, struct ioinfo *info)
{
struct virtio_backing *file = &dev->file;
if (file->pwrite(file->p, info->buf, info->len, info->offset) != info->len) {
log_warn("vioblk write error");
return EIO;
}
return 0;
}
/*
* XXX in various cases, ds should be set to VIRTIO_BLK_S_IOERR, if we can
* Process virtqueue notifications. If an unrecoverable error occurs, puts
* device into a "needs reset" state.
*
* Returns 1 if an we need to assert an IRQ.
*/
int
static int
vioblk_notifyq(struct vioblk_dev *dev)
{
uint16_t idx, cmd_desc_idx, secdata_desc_idx, ds_desc_idx;
uint32_t cmd_len;
uint16_t idx, cmd_desc_idx;
uint8_t ds;
int cnt;
off_t secbias;
off_t offset;
ssize_t sz;
int is_write, notify, i;
char *vr;
struct vring_desc *desc, *cmd_desc, *secdata_desc, *ds_desc;
struct vring_desc *table, *desc;
struct vring_avail *avail;
struct vring_used *used;
struct virtio_blk_req_hdr cmd;
struct virtio_blk_req_hdr *cmd;
struct virtio_vq_info *vq_info;
/* Invalid queue? */
@ -400,253 +312,117 @@ vioblk_notifyq(struct vioblk_dev *dev)
return (0);
vq_info = &dev->vq[dev->cfg.queue_notify];
idx = vq_info->last_avail;
vr = vq_info->q_hva;
if (vr == NULL)
fatalx("%s: null vring", __func__);
/* Compute offsets in ring of descriptors, avail ring, and used ring */
desc = (struct vring_desc *)(vr);
/* Compute offsets in table of descriptors, avail ring, and used ring */
table = (struct vring_desc *)(vr);
avail = (struct vring_avail *)(vr + vq_info->vq_availoffset);
used = (struct vring_used *)(vr + vq_info->vq_usedoffset);
idx = vq_info->last_avail & VIOBLK_QUEUE_MASK;
while (idx != avail->idx) {
/* Retrieve Command descriptor. */
cmd_desc_idx = avail->ring[idx & VIOBLK_QUEUE_MASK];
desc = &table[cmd_desc_idx];
cmd_len = desc->len;
if ((avail->idx & VIOBLK_QUEUE_MASK) == idx) {
log_debug("%s - nothing to do?", __func__);
return (0);
}
while (idx != (avail->idx & VIOBLK_QUEUE_MASK)) {
ds = VIRTIO_BLK_S_IOERR;
cmd_desc_idx = avail->ring[idx] & VIOBLK_QUEUE_MASK;
cmd_desc = &desc[cmd_desc_idx];
if ((cmd_desc->flags & VRING_DESC_F_NEXT) == 0) {
log_warnx("unchained vioblk cmd descriptor received "
"(idx %d)", cmd_desc_idx);
goto out;
/*
* Validate Command descriptor. It should be chained to another
* descriptor and not be itself writable.
*/
if ((desc->flags & VRING_DESC_F_NEXT) == 0) {
log_warnx("%s: unchained cmd descriptor", __func__);
goto reset;
}
if (DESC_WRITABLE(desc)) {
log_warnx("%s: invalid cmd descriptor state", __func__);
goto reset;
}
/* Read command from descriptor ring */
if (cmd_desc->flags & VRING_DESC_F_WRITE) {
log_warnx("vioblk: unexpected writable cmd descriptor "
"%d", cmd_desc_idx);
goto out;
}
if (read_mem(cmd_desc->addr, &cmd, sizeof(cmd))) {
log_warnx("vioblk: command read_mem error @ 0x%llx",
cmd_desc->addr);
goto out;
}
/* Retrieve the vioblk command request. */
cmd = hvaddr_mem(desc->addr, sizeof(*cmd));
if (cmd == NULL)
goto reset;
switch (cmd.type) {
/* Advance to the 2nd descriptor. */
desc = &table[desc->next & VIOBLK_QUEUE_MASK];
/* Process each available command & chain. */
switch (cmd->type) {
case VIRTIO_BLK_T_IN:
/* first descriptor */
secdata_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
secdata_desc = &desc[secdata_desc_idx];
if ((secdata_desc->flags & VRING_DESC_F_NEXT) == 0) {
log_warnx("unchained vioblk data descriptor "
"received (idx %d)", cmd_desc_idx);
goto out;
}
cnt = 0;
secbias = 0;
do {
struct ioinfo *info;
const uint8_t *secdata;
if ((secdata_desc->flags & VRING_DESC_F_WRITE)
== 0) {
log_warnx("vioblk: unwritable data "
"descriptor %d", secdata_desc_idx);
goto out;
}
info = vioblk_start_read(dev,
cmd.sector + secbias, secdata_desc->len);
if (info == NULL) {
log_warnx("vioblk: can't start read");
goto out;
}
/* read the data, use current data descriptor */
secdata = vioblk_finish_read(dev, info);
if (secdata == NULL) {
vioblk_free_info(info);
log_warnx("vioblk: block read error, "
"sector %lld", cmd.sector);
goto out;
}
if (write_mem(secdata_desc->addr, secdata,
secdata_desc->len)) {
log_warnx("can't write sector "
"data to gpa @ 0x%llx",
secdata_desc->addr);
vioblk_free_info(info);
goto out;
}
vioblk_free_info(info);
secbias += (secdata_desc->len /
VIRTIO_BLK_SECTOR_SIZE);
secdata_desc_idx = secdata_desc->next &
VIOBLK_QUEUE_MASK;
secdata_desc = &desc[secdata_desc_idx];
/* Guard against infinite chains */
if (++cnt >= VIOBLK_QUEUE_SIZE) {
log_warnx("%s: descriptor table "
"invalid", __func__);
goto out;
}
} while (secdata_desc->flags & VRING_DESC_F_NEXT);
ds_desc_idx = secdata_desc_idx;
ds_desc = secdata_desc;
ds = VIRTIO_BLK_S_OK;
break;
case VIRTIO_BLK_T_OUT:
secdata_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
secdata_desc = &desc[secdata_desc_idx];
if ((secdata_desc->flags & VRING_DESC_F_NEXT) == 0) {
log_warnx("wr vioblk: unchained vioblk data "
"descriptor received (idx %d)",
cmd_desc_idx);
goto out;
}
if (secdata_desc->len > dev->max_xfer) {
log_warnx("%s: invalid read size %d requested",
__func__, secdata_desc->len);
goto out;
}
cnt = 0;
secbias = 0;
do {
struct ioinfo *info;
if (secdata_desc->flags & VRING_DESC_F_WRITE) {
log_warnx("wr vioblk: unexpected "
"writable data descriptor %d",
secdata_desc_idx);
goto out;
}
info = vioblk_start_write(dev,
cmd.sector + secbias,
secdata_desc->addr, secdata_desc->len);
if (info == NULL) {
log_warnx("wr vioblk: can't read "
"sector data @ 0x%llx",
secdata_desc->addr);
goto out;
}
if (vioblk_finish_write(dev, info)) {
log_warnx("wr vioblk: disk write "
"error");
vioblk_free_info(info);
goto out;
}
vioblk_free_info(info);
secbias += secdata_desc->len /
VIRTIO_BLK_SECTOR_SIZE;
secdata_desc_idx = secdata_desc->next &
VIOBLK_QUEUE_MASK;
secdata_desc = &desc[secdata_desc_idx];
/* Guard against infinite chains */
if (++cnt >= VIOBLK_QUEUE_SIZE) {
log_warnx("%s: descriptor table "
"invalid", __func__);
goto out;
}
} while (secdata_desc->flags & VRING_DESC_F_NEXT);
ds_desc_idx = secdata_desc_idx;
ds_desc = secdata_desc;
ds = VIRTIO_BLK_S_OK;
break;
case VIRTIO_BLK_T_FLUSH:
case VIRTIO_BLK_T_FLUSH_OUT:
ds_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
ds_desc = &desc[ds_desc_idx];
ds = VIRTIO_BLK_S_UNSUPP;
/* Read (IN) & Write (OUT) */
is_write = (cmd->type == VIRTIO_BLK_T_OUT) ? 1 : 0;
offset = cmd->sector * VIRTIO_BLK_SECTOR_SIZE;
sz = vioblk_rw(dev, is_write, offset, table, &desc);
if (sz == -1)
ds = VIRTIO_BLK_S_IOERR;
else
ds = VIRTIO_BLK_S_OK;
break;
case VIRTIO_BLK_T_GET_ID:
secdata_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
secdata_desc = &desc[secdata_desc_idx];
/*
* We don't support this command yet. While it's not
* officially part of the virtio spec (will be in v1.2)
* there's no feature to negotiate. Linux drivers will
* often send this command regardless.
*
* When the command is received, it should appear as a
* chain of 3 descriptors, similar to the IN/OUT
* commands. The middle descriptor should have have a
* length of VIRTIO_BLK_ID_BYTES bytes.
*/
if ((secdata_desc->flags & VRING_DESC_F_NEXT) == 0) {
log_warnx("id vioblk: unchained vioblk data "
"descriptor received (idx %d)",
cmd_desc_idx);
goto out;
}
/* Skip the data descriptor. */
ds_desc_idx = secdata_desc->next & VIOBLK_QUEUE_MASK;
ds_desc = &desc[ds_desc_idx];
ds = VIRTIO_BLK_S_UNSUPP;
break;
default:
log_warnx("%s: unsupported command 0x%x", __func__,
cmd.type);
ds_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
ds_desc = &desc[ds_desc_idx];
log_warnx("%s: unsupported vioblk command %d", __func__,
cmd->type);
ds = VIRTIO_BLK_S_UNSUPP;
break;
}
if ((ds_desc->flags & VRING_DESC_F_WRITE) == 0) {
log_warnx("%s: ds descriptor %d unwritable", __func__,
ds_desc_idx);
goto out;
}
if (write_mem(ds_desc->addr, &ds, sizeof(ds))) {
log_warnx("%s: can't write device status data @ 0x%llx",
__func__, ds_desc->addr);
goto out;
/* Advance to the end of the chain, if needed. */
i = 0;
while (desc->flags & VRING_DESC_F_NEXT) {
desc = &table[desc->next & VIOBLK_QUEUE_MASK];
if (++i >= VIOBLK_QUEUE_SIZE) {
/*
* If we encounter an infinite/looping chain,
* not much we can do but say we need a reset.
*/
log_warnx("%s: descriptor chain overflow",
__func__);
goto reset;
}
}
dev->cfg.isr_status = 1;
/* Provide the status of our command processing. */
if (!DESC_WRITABLE(desc)) {
log_warnx("%s: status descriptor unwritable", __func__);
goto reset;
}
/* Overkill as ds is 1 byte, but validates gpa. */
if (write_mem(desc->addr, &ds, sizeof(ds)))
log_warnx("%s: can't write device status data "
"@ 0x%llx",__func__, desc->addr);
dev->cfg.isr_status |= 1;
notify = 1;
used->ring[used->idx & VIOBLK_QUEUE_MASK].id = cmd_desc_idx;
used->ring[used->idx & VIOBLK_QUEUE_MASK].len = cmd_desc->len;
used->ring[used->idx & VIOBLK_QUEUE_MASK].len = cmd_len;
__sync_synchronize();
used->idx++;
vq_info->last_avail = avail->idx & VIOBLK_QUEUE_MASK;
idx = (idx + 1) & VIOBLK_QUEUE_MASK;
idx++;
}
out:
vq_info->last_avail = idx;
return (notify);
reset:
/*
* When setting the "needs reset" flag, the driver is notified
* via a configuration change interrupt.
*/
dev->cfg.device_status |= DEVICE_NEEDS_RESET;
dev->cfg.isr_status |= VIRTIO_CONFIG_ISR_CONFIG_CHANGE;
return (1);
}
@ -815,9 +591,12 @@ handle_io_write(struct viodev_msg *msg, struct virtio_dev *dev)
vioblk_update_qs(vioblk);
break;
case VIRTIO_CONFIG_QUEUE_NOTIFY:
vioblk->cfg.queue_notify = data;
if (vioblk_notifyq(vioblk))
intr = 1;
/* XXX We should be stricter about status checks. */
if (!(vioblk->cfg.device_status & DEVICE_NEEDS_RESET)) {
vioblk->cfg.queue_notify = data;
if (vioblk_notifyq(vioblk))
intr = 1;
}
break;
case VIRTIO_CONFIG_DEVICE_STATUS:
vioblk->cfg.device_status = data;
@ -857,15 +636,15 @@ handle_io_read(struct viodev_msg *msg, struct virtio_dev *dev, int8_t *intr)
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI:
switch (sz) {
case 4:
data = (uint32_t)(vioblk->sz);
data = (uint32_t)(vioblk->capacity);
break;
case 2:
data &= 0xFFFF0000;
data |= (uint32_t)(vioblk->sz) & 0xFFFF;
data |= (uint32_t)(vioblk->capacity) & 0xFFFF;
break;
case 1:
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz) & 0xFF;
data |= (uint32_t)(vioblk->capacity) & 0xFF;
break;
}
/* XXX handle invalid sz */
@ -873,39 +652,39 @@ handle_io_read(struct viodev_msg *msg, struct virtio_dev *dev, int8_t *intr)
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 1:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 8) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 8) & 0xFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 2:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 16) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 16) & 0xFF;
} else if (sz == 2) {
data &= 0xFFFF0000;
data |= (uint32_t)(vioblk->sz >> 16) & 0xFFFF;
data |= (uint32_t)(vioblk->capacity >> 16) & 0xFFFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 3:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 24) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 24) & 0xFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 4:
switch (sz) {
case 4:
data = (uint32_t)(vioblk->sz >> 32);
data = (uint32_t)(vioblk->capacity >> 32);
break;
case 2:
data &= 0xFFFF0000;
data |= (uint32_t)(vioblk->sz >> 32) & 0xFFFF;
data |= (uint32_t)(vioblk->capacity >> 32) & 0xFFFF;
break;
case 1:
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 32) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 32) & 0xFF;
break;
}
/* XXX handle invalid sz */
@ -913,65 +692,65 @@ handle_io_read(struct viodev_msg *msg, struct virtio_dev *dev, int8_t *intr)
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 5:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 40) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 40) & 0xFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 6:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 48) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 48) & 0xFF;
} else if (sz == 2) {
data &= 0xFFFF0000;
data |= (uint32_t)(vioblk->sz >> 48) & 0xFFFF;
data |= (uint32_t)(vioblk->capacity >> 48) & 0xFFFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 7:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->sz >> 56) & 0xFF;
data |= (uint32_t)(vioblk->capacity >> 56) & 0xFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 8:
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 12:
switch (sz) {
case 4:
data = (uint32_t)(vioblk->max_xfer);
data = (uint32_t)(vioblk->seg_max);
break;
case 2:
data &= 0xFFFF0000;
data |= (uint32_t)(vioblk->max_xfer) & 0xFFFF;
data |= (uint32_t)(vioblk->seg_max) & 0xFFFF;
break;
case 1:
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->max_xfer) & 0xFF;
data |= (uint32_t)(vioblk->seg_max) & 0xFF;
break;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 9:
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 13:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->max_xfer >> 8) & 0xFF;
data |= (uint32_t)(vioblk->seg_max >> 8) & 0xFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 10:
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 14:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->max_xfer >> 16) & 0xFF;
data |= (uint32_t)(vioblk->seg_max >> 16) & 0xFF;
} else if (sz == 2) {
data &= 0xFFFF0000;
data |= (uint32_t)(vioblk->max_xfer >> 16)
data |= (uint32_t)(vioblk->seg_max >> 16)
& 0xFFFF;
}
/* XXX handle invalid sz */
break;
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 11:
case VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI + 15:
if (sz == 1) {
data &= 0xFFFFFF00;
data |= (uint32_t)(vioblk->max_xfer >> 24) & 0xFF;
data |= (uint32_t)(vioblk->seg_max >> 24) & 0xFF;
}
/* XXX handle invalid sz */
break;
@ -1008,3 +787,84 @@ handle_io_read(struct viodev_msg *msg, struct virtio_dev *dev, int8_t *intr)
return (data);
}
/*
* Emulate read/write io. Walks the descriptor chain, collecting io work and
* then emulates the read or write.
*
* On success, returns bytes read/written.
* On error, returns -1 and descriptor (desc) remains at its current position.
*/
static ssize_t
vioblk_rw(struct vioblk_dev *dev, int is_write, off_t offset,
struct vring_desc *desc_tbl, struct vring_desc **desc)
{
struct iovec *iov = NULL;
ssize_t sz = 0;
size_t io_idx = 0; /* Index into iovec workqueue. */
size_t xfer_sz = 0; /* Total accumulated io bytes. */
do {
iov = &io_v[io_idx];
/*
* Reads require writable descriptors. Writes require
* non-writeable descriptors.
*/
if ((!is_write) ^ DESC_WRITABLE(*desc)) {
log_warnx("%s: invalid descriptor for %s command",
__func__, is_write ? "write" : "read");
return (-1);
}
/* Collect the IO segment information. */
iov->iov_len = (size_t)(*desc)->len;
iov->iov_base = hvaddr_mem((*desc)->addr, iov->iov_len);
if (iov->iov_base == NULL)
return (-1);
/* Move our counters. */
xfer_sz += iov->iov_len;
io_idx++;
/* Guard against infinite chains */
if (io_idx >= nitems(io_v)) {
log_warnx("%s: descriptor table "
"invalid", __func__);
return (-1);
}
/* Advance to the next descriptor. */
*desc = &desc_tbl[(*desc)->next & VIOBLK_QUEUE_MASK];
} while ((*desc)->flags & VRING_DESC_F_NEXT);
/*
* Validate the requested block io operation alignment and size.
* Checking offset is just an extra caution as it is derived from
* a disk sector and is done for completeness in bounds checking.
*/
if (offset % VIRTIO_BLK_SECTOR_SIZE != 0 &&
xfer_sz % VIRTIO_BLK_SECTOR_SIZE != 0) {
log_warnx("%s: unaligned read", __func__);
return (-1);
}
if (xfer_sz > SSIZE_MAX) { /* iovec_copyin limit */
log_warnx("%s: invalid %s size: %zu", __func__,
is_write ? "write" : "read", xfer_sz);
return (-1);
}
/* Emulate the Read or Write operation. */
if (is_write)
sz = dev->file.pwritev(dev->file.p, io_v, io_idx, offset);
else
sz = dev->file.preadv(dev->file.p, io_v, io_idx, offset);
if (sz != (ssize_t)xfer_sz) {
log_warnx("%s: %s failure at offset 0x%llx, xfer_sz=%zu, "
"sz=%ld", __func__, (is_write ? "write" : "read"), offset,
xfer_sz, sz);
return (-1);
}
return (sz);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vioqcow2.c,v 1.23 2023/05/28 05:28:50 asou Exp $ */
/* $OpenBSD: vioqcow2.c,v 1.24 2023/09/14 15:25:43 dv Exp $ */
/*
* Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
@ -105,7 +105,9 @@ static void inc_refs(struct qcdisk *, off_t, int);
static off_t mkcluster(struct qcdisk *, struct qcdisk *, off_t, off_t);
static int qc2_open(struct qcdisk *, int *, size_t);
static ssize_t qc2_pread(void *, char *, size_t, off_t);
static ssize_t qc2_preadv(void *, struct iovec *, int, off_t);
static ssize_t qc2_pwrite(void *, char *, size_t, off_t);
static ssize_t qc2_pwritev(void *, struct iovec *, int, off_t);
static void qc2_close(void *, int);
/*
@ -128,7 +130,9 @@ virtio_qcow2_init(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd)
}
file->p = diskp;
file->pread = qc2_pread;
file->preadv = qc2_preadv;
file->pwrite = qc2_pwrite;
file->pwritev = qc2_pwritev;
file->close = qc2_close;
*szp = diskp->disksz;
return 0;
@ -304,6 +308,24 @@ qc2_open(struct qcdisk *disk, int *fds, size_t nfd)
return 0;
}
static ssize_t
qc2_preadv(void *p, struct iovec *iov, int cnt, off_t offset)
{
int i;
off_t pos = offset;
ssize_t sz = 0, total = 0;
for (i = 0; i < cnt; i++, iov++) {
sz = qc2_pread(p, iov->iov_base, iov->iov_len, pos);
if (sz == -1)
return (sz);
total += sz;
pos += sz;
}
return (total);
}
static ssize_t
qc2_pread(void *p, char *buf, size_t len, off_t off)
{
@ -359,7 +381,25 @@ qc2_pread(void *p, char *buf, size_t len, off_t off)
return len;
}
ssize_t
static ssize_t
qc2_pwritev(void *p, struct iovec *iov, int cnt, off_t offset)
{
int i;
off_t pos = offset;
ssize_t sz = 0, total = 0;
for (i = 0; i < cnt; i++, iov++) {
sz = qc2_pwrite(p, iov->iov_base, iov->iov_len, pos);
if (sz == -1)
return (sz);
total += sz;
pos += sz;
}
return (total);
}
static ssize_t
qc2_pwrite(void *p, char *buf, size_t len, off_t off)
{
struct qcdisk *disk, *d;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vioraw.c,v 1.10 2023/05/28 05:28:50 asou Exp $ */
/* $OpenBSD: vioraw.c,v 1.11 2023/09/14 15:25:43 dv Exp $ */
/*
* Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
*
@ -31,12 +31,24 @@ raw_pread(void *file, char *buf, size_t len, off_t off)
return pread(*(int *)file, buf, len, off);
}
static ssize_t
raw_preadv(void *file, struct iovec *iov, int cnt, off_t offset)
{
return preadv(*(int *)file, iov, cnt, offset);
}
static ssize_t
raw_pwrite(void *file, char *buf, size_t len, off_t off)
{
return pwrite(*(int *)file, buf, len, off);
}
static ssize_t
raw_pwritev(void *file, struct iovec *iov, int cnt, off_t offset)
{
return pwritev(*(int *)file, iov, cnt, offset);
}
static void
raw_close(void *file, int stayopen)
{
@ -68,7 +80,9 @@ virtio_raw_init(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd)
*fdp = fd[0];
file->p = fdp;
file->pread = raw_pread;
file->preadv = raw_preadv;
file->pwrite = raw_pwrite;
file->pwritev = raw_pwritev;
file->close = raw_close;
*szp = sz;
return (0);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: virtio.c,v 1.106 2023/07/27 09:27:43 dv Exp $ */
/* $OpenBSD: virtio.c,v 1.107 2023/09/14 15:25:43 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@ -650,8 +650,8 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
+ sizeof(uint16_t) * (2 + VIOBLK_QUEUE_SIZE));
dev->vioblk.vq[0].last_avail = 0;
dev->vioblk.cfg.device_feature =
VIRTIO_BLK_F_SIZE_MAX;
dev->vioblk.max_xfer = 1048576;
VIRTIO_BLK_F_SEG_MAX;
dev->vioblk.seg_max = VIOBLK_SEG_MAX;
/*
* Initialize disk fds to an invalid fd (-1), then

View File

@ -1,4 +1,4 @@
/* $OpenBSD: virtio.h,v 1.47 2023/09/06 19:26:39 dv Exp $ */
/* $OpenBSD: virtio.h,v 1.48 2023/09/14 15:25:43 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@ -33,12 +33,13 @@
#define ALIGNSZ(sz, align) ((sz + align - 1) & ~(align - 1))
#define MIN(a,b) (((a)<(b))?(a):(b))
/* Queue sizes must be power of two */
/* Queue sizes must be power of two and less than IOV_MAX (1024). */
#define VIORND_QUEUE_SIZE 64
#define VIORND_QUEUE_MASK (VIORND_QUEUE_SIZE - 1)
#define VIOBLK_QUEUE_SIZE 128
#define VIOBLK_QUEUE_MASK (VIOBLK_QUEUE_SIZE - 1)
#define VIOBLK_SEG_MAX (VIOBLK_QUEUE_SIZE - 2)
#define VIOSCSI_QUEUE_SIZE 128
#define VIOSCSI_QUEUE_MASK (VIOSCSI_QUEUE_SIZE - 1)
@ -69,6 +70,10 @@
* Rename the address config register to be more descriptive.
*/
#define VIRTIO_CONFIG_QUEUE_PFN VIRTIO_CONFIG_QUEUE_ADDRESS
#define DEVICE_NEEDS_RESET VIRTIO_CONFIG_DEVICE_STATUS_DEVICE_NEEDS_RESET
#define DESC_WRITABLE(/* struct vring_desc */ x) \
(((x)->flags & VRING_DESC_F_WRITE) ? 1 : 0)
/*
* VM <-> Device messaging.
@ -115,9 +120,11 @@ struct virtio_io_cfg {
struct virtio_backing {
void *p;
ssize_t (*pread)(void *p, char *buf, size_t len, off_t off);
ssize_t (*pwrite)(void *p, char *buf, size_t len, off_t off);
void (*close)(void *p, int);
ssize_t (*pread)(void *, char *, size_t, off_t);
ssize_t (*preadv)(void *, struct iovec *, int, off_t);
ssize_t (*pwrite)(void *, char *, size_t, off_t);
ssize_t (*pwritev)(void *, struct iovec *, int, off_t);
void (*close)(void *, int);
};
/*
@ -212,8 +219,8 @@ struct vioblk_dev {
int disk_fd[VM_MAX_BASE_PER_DISK]; /* fds for disk image(s) */
uint8_t ndisk_fd; /* number of valid disk fds */
uint64_t sz; /* size in 512 byte sectors */
uint32_t max_xfer;
uint64_t capacity; /* size in 512 byte sectors */
uint32_t seg_max; /* maximum number of segments */
unsigned int idx;
};
@ -318,6 +325,7 @@ struct vmmci_dev {
uint8_t pci_id;
};
/* XXX to be removed once vioscsi is adapted to vectorized io. */
struct ioinfo {
uint8_t *buf;
ssize_t len;
@ -354,9 +362,6 @@ int virtio_raw_init(struct virtio_backing *, off_t *, int*, size_t);
int vioblk_dump(int);
int vioblk_restore(int, struct vmd_vm *, int[][VM_MAX_BASE_PER_DISK]);
void vioblk_update_qs(struct vioblk_dev *);
void vioblk_update_qa(struct vioblk_dev *);
int vioblk_notifyq(struct vioblk_dev *);
int vionet_dump(int);
int vionet_restore(int, struct vmd_vm *, int *);