Skip to content

Commit e835f5f

Browse files
peterfangwenlingz
authored andcommitted
dm: enforce data size when accessing PCI BARs
Always enforce data size when using BAR access functions. Currently, the size serves as a hint to the BAR access functions and these functions are expected to behave accordingly. Some of the access functions, e.g. virtio ones, don't always truncate the data but expect the caller to take care of the data size. This causes problems with OVMF's virtio drivers during I/O instruction emulation because RAX can contain junk bits that shouldn't be written to the device. v1 -> v2: - improve readability Tracked-On: #1935 Signed-off-by: Peter Fang <peter.fang@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
1 parent f5a66e8 commit e835f5f

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

devicemodel/hw/pci/core.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,17 @@ pci_msix_pba_bar(struct pci_vdev *dev)
355355
return -1;
356356
}
357357

358+
static inline uint64_t
359+
bar_value(int size, uint64_t val)
360+
{
361+
uint64_t mask;
362+
363+
assert(size == 1 || size == 2 || size == 4 || size == 8);
364+
mask = (size < 8 ? 1UL << (size * 8) : 0UL) - 1;
365+
366+
return val & mask;
367+
}
368+
358369
static int
359370
pci_emul_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
360371
uint32_t *eax, void *arg)
@@ -369,12 +380,13 @@ pci_emul_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
369380
port >= pdi->bar[i].addr &&
370381
port + bytes <= pdi->bar[i].addr + pdi->bar[i].size) {
371382
offset = port - pdi->bar[i].addr;
372-
if (in)
383+
if (in) {
373384
*eax = (*ops->vdev_barread)(ctx, vcpu, pdi, i,
374-
offset, bytes);
375-
else
385+
offset, bytes);
386+
*eax = bar_value(bytes, *eax);
387+
} else
376388
(*ops->vdev_barwrite)(ctx, vcpu, pdi, i, offset,
377-
bytes, *eax);
389+
bytes, bar_value(bytes, *eax));
378390
return 0;
379391
}
380392
}
@@ -406,17 +418,24 @@ pci_emul_mem_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
406418
4, *val >> 32);
407419
} else {
408420
(*ops->vdev_barwrite)(ctx, vcpu, pdi, bidx, offset,
409-
size, *val);
421+
size, bar_value(size, *val));
410422
}
411423
} else {
412424
if (size == 8) {
413-
*val = (*ops->vdev_barread)(ctx, vcpu, pdi, bidx,
414-
offset, 4);
415-
*val |= (*ops->vdev_barread)(ctx, vcpu, pdi, bidx,
416-
offset + 4, 4) << 32;
425+
uint64_t val_lo, val_hi;
426+
427+
val_lo = (*ops->vdev_barread)(ctx, vcpu, pdi, bidx,
428+
offset, 4);
429+
val_lo = bar_value(4, val_lo);
430+
431+
val_hi = (*ops->vdev_barread)(ctx, vcpu, pdi, bidx,
432+
offset + 4, 4);
433+
434+
*val = val_lo | (val_hi << 32);
417435
} else {
418436
*val = (*ops->vdev_barread)(ctx, vcpu, pdi, bidx,
419-
offset, size);
437+
offset, size);
438+
*val = bar_value(size, *val);
420439
}
421440
}
422441

0 commit comments

Comments
 (0)