pc,pci,vhost,virtio: misc fixes
Just a bunch of bugfixes all over the place. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAl+cCq8PHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRpKWkH/0qq+u2z/q0KYzmodcdW2eFNsvKF2e+Dz3Af zZGMREH93DsKAQ2k3t84sz2RAaAP45cCqrq+v8kSzmpaC7GqKYA/VceeLwy8e6Eu YKvu5QixrOVTpNg2QV/w44ywgtA4NbWy5Fr9S4qhzPyyD/gtE609weZ1vQnSFT7B Gg4vr1lcqskwYTH7sh+bpsDTUeANr7QaknWKnaomroz+IUO8m9ig6RKtegaXhQCj xswI4458S3nklqnoGMa56j46VYwft8YHO1lBiR1WefTHylknyng9Tdvf9G5mnzVg wyrMTuT36lMXIa5KcSZeECIt2ZUT6KSSjWzEKZNXL5lS3gfUo7o= =powp -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging pc,pci,vhost,virtio: misc fixes Just a bunch of bugfixes all over the place. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Fri 30 Oct 2020 12:44:31 GMT # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: intel_iommu: Fix two misuse of "0x%u" prints virtio: skip guest index check on device load vhost-blk: set features before setting inflight feature pci: Disallow improper BAR registration for type 1 pci: Change error_report to assert(3) pci: advertise a page aligned ATS pc: Implement -no-hpet as sugar for -machine hpet=on vhost: Don't special case vq->used_phys in vhost_get_log_size() pci: Assert irqnum is between 0 and bus->nirqs in pci_bus_change_irq_level hw/pci: Extract pci_bus_change_irq_level() from pci_change_irq_level() hw/virtio/vhost-vdpa: Fix Coverity CID 1432864 acpi/crs: Support ranges > 32b for hosts acpi/crs: Prevent bad ranges for host bridges vhost-vsock: set vhostfd to non-blocking mode vhost-vdpa: negotiate VIRTIO_NET_F_STATUS with driver Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
700d20b49e
|
@ -131,6 +131,12 @@ static int vhost_user_blk_start(VirtIODevice *vdev)
|
|||
|
||||
s->dev.acked_features = vdev->guest_features;
|
||||
|
||||
ret = vhost_dev_prepare_inflight(&s->dev);
|
||||
if (ret < 0) {
|
||||
error_report("Error set inflight format: %d", -ret);
|
||||
goto err_guest_notifiers;
|
||||
}
|
||||
|
||||
if (!s->inflight->addr) {
|
||||
ret = vhost_dev_get_inflight(&s->dev, s->queue_size, s->inflight);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -786,8 +786,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
|
|||
crs_range_insert(temp_range_set.io_ranges,
|
||||
range_base, range_limit);
|
||||
} else { /* "memory" */
|
||||
crs_range_insert(temp_range_set.mem_ranges,
|
||||
range_base, range_limit);
|
||||
uint64_t length = range_limit - range_base + 1;
|
||||
if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
|
||||
crs_range_insert(temp_range_set.mem_ranges, range_base,
|
||||
range_limit);
|
||||
} else {
|
||||
crs_range_insert(temp_range_set.mem_64bit_ranges,
|
||||
range_base, range_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,6 +872,8 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
|
|||
crs_range_merge(temp_range_set.mem_ranges);
|
||||
for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
|
||||
entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
|
||||
assert(entry->limit <= UINT32_MAX &&
|
||||
(entry->limit - entry->base + 1) <= UINT32_MAX);
|
||||
aml_append(crs,
|
||||
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
|
||||
AML_MAX_FIXED, AML_NON_CACHEABLE,
|
||||
|
|
|
@ -2665,7 +2665,7 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)
|
|||
|
||||
if (addr + size > DMAR_REG_SIZE) {
|
||||
error_report_once("%s: MMIO over range: addr=0x%" PRIx64
|
||||
" size=0x%u", __func__, addr, size);
|
||||
" size=0x%x", __func__, addr, size);
|
||||
return (uint64_t)-1;
|
||||
}
|
||||
|
||||
|
@ -2716,7 +2716,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
|
|||
|
||||
if (addr + size > DMAR_REG_SIZE) {
|
||||
error_report_once("%s: MMIO over range: addr=0x%" PRIx64
|
||||
" size=0x%u", __func__, addr, size);
|
||||
" size=0x%x", __func__, addr, size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
63
hw/i386/pc.c
63
hw/i386/pc.c
|
@ -1142,28 +1142,31 @@ void pc_basic_device_init(struct PCMachineState *pcms,
|
|||
* Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
|
||||
* when the HPET wants to take over. Thus we have to disable the latter.
|
||||
*/
|
||||
if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
|
||||
if (pcms->hpet_enabled && (!kvm_irqchip_in_kernel() ||
|
||||
kvm_has_pit_state2())) {
|
||||
hpet = qdev_try_new(TYPE_HPET);
|
||||
if (hpet) {
|
||||
/* For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7
|
||||
* and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23,
|
||||
* IRQ8 and IRQ2.
|
||||
*/
|
||||
uint8_t compat = object_property_get_uint(OBJECT(hpet),
|
||||
HPET_INTCAP, NULL);
|
||||
if (!compat) {
|
||||
qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs);
|
||||
}
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(hpet), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE);
|
||||
|
||||
for (i = 0; i < GSI_NUM_PINS; i++) {
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
|
||||
}
|
||||
pit_isa_irq = -1;
|
||||
pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
|
||||
rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
|
||||
if (!hpet) {
|
||||
error_report("couldn't create HPET device");
|
||||
exit(1);
|
||||
}
|
||||
/* For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7
|
||||
* and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23,
|
||||
* IRQ8 and IRQ2.
|
||||
*/
|
||||
uint8_t compat = object_property_get_uint(OBJECT(hpet),
|
||||
HPET_INTCAP, NULL);
|
||||
if (!compat) {
|
||||
qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs);
|
||||
}
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(hpet), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE);
|
||||
|
||||
for (i = 0; i < GSI_NUM_PINS; i++) {
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
|
||||
}
|
||||
pit_isa_irq = -1;
|
||||
pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
|
||||
rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
|
||||
}
|
||||
*rtc_state = mc146818_rtc_init(isa_bus, 2000, rtc_irq);
|
||||
|
||||
|
@ -1529,6 +1532,20 @@ static void pc_machine_set_pit(Object *obj, bool value, Error **errp)
|
|||
pcms->pit_enabled = value;
|
||||
}
|
||||
|
||||
static bool pc_machine_get_hpet(Object *obj, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
return pcms->hpet_enabled;
|
||||
}
|
||||
|
||||
static void pc_machine_set_hpet(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
pcms->hpet_enabled = value;
|
||||
}
|
||||
|
||||
static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
|
@ -1579,6 +1596,9 @@ static void pc_machine_initfn(Object *obj)
|
|||
pcms->smbus_enabled = true;
|
||||
pcms->sata_enabled = true;
|
||||
pcms->pit_enabled = true;
|
||||
#ifdef CONFIG_HPET
|
||||
pcms->hpet_enabled = true;
|
||||
#endif
|
||||
|
||||
pc_system_flash_create(pcms);
|
||||
pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
|
||||
|
@ -1699,6 +1719,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
|||
|
||||
object_class_property_add_bool(oc, PC_MACHINE_PIT,
|
||||
pc_machine_get_pit, pc_machine_set_pit);
|
||||
|
||||
object_class_property_add_bool(oc, "hpet",
|
||||
pc_machine_get_hpet, pc_machine_set_hpet);
|
||||
}
|
||||
|
||||
static const TypeInfo pc_machine_info = {
|
||||
|
|
|
@ -216,7 +216,7 @@ static void pc_init1(MachineState *machine,
|
|||
i440fx_state = NULL;
|
||||
isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
|
||||
&error_abort);
|
||||
no_hpet = 1;
|
||||
pcms->hpet_enabled = false;
|
||||
}
|
||||
isa_bus_irqs(isa_bus, x86ms->gsi);
|
||||
|
||||
|
|
23
hw/pci/pci.c
23
hw/pci/pci.c
|
@ -248,6 +248,14 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
|
|||
d->irq_state |= level << irq_num;
|
||||
}
|
||||
|
||||
static void pci_bus_change_irq_level(PCIBus *bus, int irq_num, int change)
|
||||
{
|
||||
assert(irq_num >= 0);
|
||||
assert(irq_num < bus->nirq);
|
||||
bus->irq_count[irq_num] += change;
|
||||
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
|
||||
}
|
||||
|
||||
static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
|
||||
{
|
||||
PCIBus *bus;
|
||||
|
@ -258,8 +266,7 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
|
|||
break;
|
||||
pci_dev = bus->parent_dev;
|
||||
}
|
||||
bus->irq_count[irq_num] += change;
|
||||
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
|
||||
pci_bus_change_irq_level(bus, irq_num, change);
|
||||
}
|
||||
|
||||
int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
|
||||
|
@ -1141,14 +1148,16 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
|
|||
uint32_t addr; /* offset in pci config space */
|
||||
uint64_t wmask;
|
||||
pcibus_t size = memory_region_size(memory);
|
||||
uint8_t hdr_type;
|
||||
|
||||
assert(region_num >= 0);
|
||||
assert(region_num < PCI_NUM_REGIONS);
|
||||
if (size & (size-1)) {
|
||||
error_report("ERROR: PCI region size must be pow2 "
|
||||
"type=0x%x, size=0x%"FMT_PCIBUS"", type, size);
|
||||
exit(1);
|
||||
}
|
||||
assert(is_power_of_2(size));
|
||||
|
||||
/* A PCI bridge device (with Type 1 header) may only have at most 2 BARs */
|
||||
hdr_type =
|
||||
pci_dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
|
||||
assert(hdr_type != PCI_HEADER_TYPE_BRIDGE || region_num < 2);
|
||||
|
||||
r = &pci_dev->io_regions[region_num];
|
||||
r->addr = PCI_BAR_UNMAPPED;
|
||||
|
|
|
@ -971,8 +971,9 @@ void pcie_ats_init(PCIDevice *dev, uint16_t offset)
|
|||
|
||||
dev->exp.ats_cap = offset;
|
||||
|
||||
/* Invalidate Queue Depth 0, Page Aligned Request 0 */
|
||||
pci_set_word(dev->config + offset + PCI_ATS_CAP, 0);
|
||||
/* Invalidate Queue Depth 0, Page Aligned Request 1 */
|
||||
pci_set_word(dev->config + offset + PCI_ATS_CAP,
|
||||
PCI_ATS_CAP_PAGE_ALIGNED);
|
||||
/* STU 0, Disabled by default */
|
||||
pci_set_word(dev->config + offset + PCI_ATS_CTRL, 0);
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ static void vhost_vdpa_listener_begin(MemoryListener *listener)
|
|||
{
|
||||
struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
|
||||
struct vhost_dev *dev = v->dev;
|
||||
struct vhost_msg_v2 msg;
|
||||
struct vhost_msg_v2 msg = {};
|
||||
int fd = v->device_fd;
|
||||
|
||||
if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) {
|
||||
|
@ -110,7 +110,7 @@ static void vhost_vdpa_listener_commit(MemoryListener *listener)
|
|||
{
|
||||
struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
|
||||
struct vhost_dev *dev = v->dev;
|
||||
struct vhost_msg_v2 msg;
|
||||
struct vhost_msg_v2 msg = {};
|
||||
int fd = v->device_fd;
|
||||
|
||||
if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "qapi/error.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/virtio/vhost-vsock.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
@ -148,6 +149,13 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
|
|||
error_prepend(errp, "vhost-vsock: unable to parse vhostfd: ");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = qemu_try_set_nonblock(vhostfd);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"vhost-vsock: unable to set non-blocking mode");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
vhostfd = open("/dev/vhost-vsock", O_RDWR);
|
||||
if (vhostfd < 0) {
|
||||
|
@ -155,6 +163,8 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
|
|||
"vhost-vsock: failed to open vhost device");
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_set_nonblock(vhostfd);
|
||||
}
|
||||
|
||||
vhost_vsock_common_realize(vdev, "vhost-vsock");
|
||||
|
|
|
@ -172,16 +172,6 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
|
|||
reg->memory_size);
|
||||
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||
}
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
|
||||
if (!vq->used_phys && !vq->used_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t last = vq->used_phys + vq->used_size - 1;
|
||||
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||
}
|
||||
return log_size;
|
||||
}
|
||||
|
||||
|
@ -1655,6 +1645,24 @@ int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int vhost_dev_prepare_inflight(struct vhost_dev *hdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (hdev->vhost_ops->vhost_get_inflight_fd == NULL ||
|
||||
hdev->vhost_ops->vhost_set_inflight_fd == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = vhost_dev_set_features(hdev, hdev->log_enabled);
|
||||
if (r < 0) {
|
||||
VHOST_OPS_DEBUG("vhost_dev_prepare_inflight failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vhost_dev_set_inflight(struct vhost_dev *dev,
|
||||
struct vhost_inflight *inflight)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "trace.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
|
@ -3160,12 +3161,12 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
|||
nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
|
||||
/* Check it isn't doing strange things with descriptor numbers. */
|
||||
if (nheads > vdev->vq[i].vring.num) {
|
||||
error_report("VQ %d size 0x%x Guest index 0x%x "
|
||||
"inconsistent with Host index 0x%x: delta 0x%x",
|
||||
i, vdev->vq[i].vring.num,
|
||||
vring_avail_idx(&vdev->vq[i]),
|
||||
vdev->vq[i].last_avail_idx, nheads);
|
||||
return -1;
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"VQ %d size 0x%x Guest index 0x%x "
|
||||
"inconsistent with Host index 0x%x: delta 0x%x",
|
||||
i, vdev->vq[i].vring.num,
|
||||
vring_avail_idx(&vdev->vq[i]),
|
||||
vdev->vq[i].last_avail_idx, nheads);
|
||||
}
|
||||
vdev->vq[i].used_idx = vring_used_idx(&vdev->vq[i]);
|
||||
vdev->vq[i].shadow_avail_idx = vring_avail_idx(&vdev->vq[i]);
|
||||
|
|
|
@ -43,6 +43,7 @@ typedef struct PCMachineState {
|
|||
bool smbus_enabled;
|
||||
bool sata_enabled;
|
||||
bool pit_enabled;
|
||||
bool hpet_enabled;
|
||||
|
||||
/* NUMA information: */
|
||||
uint64_t numa_nodes;
|
||||
|
|
|
@ -126,7 +126,4 @@ qemu_irq x86_allocate_cpu_irq(void);
|
|||
void gsi_handler(void *opaque, int n, int level);
|
||||
void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
|
||||
|
||||
/* hpet.c */
|
||||
extern int no_hpet;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -141,6 +141,7 @@ void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
|
|||
void vhost_dev_free_inflight(struct vhost_inflight *inflight);
|
||||
void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f);
|
||||
int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f);
|
||||
int vhost_dev_prepare_inflight(struct vhost_dev *hdev);
|
||||
int vhost_dev_set_inflight(struct vhost_dev *dev,
|
||||
struct vhost_inflight *inflight);
|
||||
int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
|
||||
|
|
|
@ -55,6 +55,7 @@ const int vdpa_feature_bits[] = {
|
|||
VIRTIO_F_IOMMU_PLATFORM,
|
||||
VIRTIO_F_RING_PACKED,
|
||||
VIRTIO_NET_F_GUEST_ANNOUNCE,
|
||||
VIRTIO_NET_F_STATUS,
|
||||
VHOST_INVALID_FEATURE_BIT
|
||||
};
|
||||
|
||||
|
|
|
@ -146,7 +146,6 @@ static Chardev **serial_hds;
|
|||
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
|
||||
int win2k_install_hack = 0;
|
||||
int singlestep = 0;
|
||||
int no_hpet = 0;
|
||||
int fd_bootchk = 1;
|
||||
static int no_reboot;
|
||||
int no_shutdown = 0;
|
||||
|
@ -3562,7 +3561,8 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||
qemu_opts_parse_noisily(olist, "acpi=off", false);
|
||||
break;
|
||||
case QEMU_OPTION_no_hpet:
|
||||
no_hpet = 1;
|
||||
olist = qemu_find_opts("machine");
|
||||
qemu_opts_parse_noisily(olist, "hpet=off", false);
|
||||
break;
|
||||
case QEMU_OPTION_no_reboot:
|
||||
no_reboot = 1;
|
||||
|
|
Loading…
Reference in a new issue