virtio,pc,pci: features, cleanups, fixes

misc fixes, cleanups
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmVrmhwPHG1zdEByZWRo
 YXQuY29tAAoJECgfDbjSjVRp/XsH/05hHtQqO+EnKSAW5SEwZnlLfzDcajVVPIkT
 h6Yf6ahHNf4hG1qqa2CICqJtDAOQYamO128QjZdQxsnYejwBmZ/oG//neWh6qLPV
 Hp4AaKV2MjKRQZPNblnrGUirxkSWSTqIONXp4FsVVpKOKW9IX5f9tH6nyFAqXWX7
 KzNY/3KD1CVSwAV1+hY2c6OzWVdTSJykPRocfB0jTYY1RygI0t57Hiq7v8AliGAx
 7ktSJFD9MBr+4Un7CQZWp24eyrL77j8U+YQRlPVYupkmQyuXHPdBr4RruHcGupIy
 GeIvbkX1mTCEfOd/HFQ1X41hpf8AEyZjjq2SOEBncIRWY6EhSio=
 =opjy
 -----END PGP SIGNATURE-----

Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging

virtio,pc,pci: features, cleanups, fixes

misc fixes, cleanups

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmVrmhwPHG1zdEByZWRo
# YXQuY29tAAoJECgfDbjSjVRp/XsH/05hHtQqO+EnKSAW5SEwZnlLfzDcajVVPIkT
# h6Yf6ahHNf4hG1qqa2CICqJtDAOQYamO128QjZdQxsnYejwBmZ/oG//neWh6qLPV
# Hp4AaKV2MjKRQZPNblnrGUirxkSWSTqIONXp4FsVVpKOKW9IX5f9tH6nyFAqXWX7
# KzNY/3KD1CVSwAV1+hY2c6OzWVdTSJykPRocfB0jTYY1RygI0t57Hiq7v8AliGAx
# 7ktSJFD9MBr+4Un7CQZWp24eyrL77j8U+YQRlPVYupkmQyuXHPdBr4RruHcGupIy
# GeIvbkX1mTCEfOd/HFQ1X41hpf8AEyZjjq2SOEBncIRWY6EhSio=
# =opjy
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 02 Dec 2023 15:57:00 EST
# 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

* tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu:
  vhost-user-scsi: free the inflight area when reset
  vhost-user: fix the reconnect error
  msix: unset PCIDevice::msix_vector_poll_notifier in rollback
  virtio-iommu: Remove useless !sdev check in virtio_iommu_probe()
  hw/i386: fix short-circuit logic with non-optimizing builds
  hw/acpi/erst: Do not ignore Error* in realize handler
  pcie_sriov: Remove g_new assertion
  virtio-sound: add realize() error cleanup path
  virtio-snd: check AUD_register_card return value
  hw/audio/hda-codec: reenable the audio mixer
  hw/audio/hda-codec: fix multiplication overflow
  hw/audio/virtio-snd-pci: fix the PCI class code
  tests/acpi/bios-tables-test: do not write new blobs unless there are changes
  netdev: set timeout depending on loadavg
  osdep: add getloadavg

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-12-04 08:02:37 -05:00
commit 173e828064
16 changed files with 152 additions and 49 deletions

View File

@ -947,6 +947,7 @@ static const VMStateDescription erst_vmstate = {
static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
{
ERRP_GUARD();
ERSTDeviceState *s = ACPIERST(pci_dev);
trace_acpi_erst_realizefn_in();
@ -964,9 +965,15 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
/* HostMemoryBackend size will be multiple of PAGE_SIZE */
s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp);
if (*errp) {
return;
}
/* Initialize backend storage and record_count */
check_erst_backend_storage(s, errp);
if (*errp) {
return;
}
/* BAR 0: Programming registers */
memory_region_init_io(&s->iomem_mr, OBJECT(pci_dev), &erst_reg_ops, s,
@ -977,6 +984,9 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
memory_region_init_ram(&s->exchange_mr, OBJECT(pci_dev),
"erst.exchange",
le32_to_cpu(s->header->record_size), errp);
if (*errp) {
return;
}
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
&s->exchange_mr);

View File

@ -22,6 +22,7 @@
#include "hw/qdev-properties.h"
#include "intel-hda.h"
#include "migration/vmstate.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "intel-hda-defs.h"
#include "audio/audio.h"
@ -189,9 +190,9 @@ struct HDAAudioState {
bool use_timer;
};
static inline int64_t hda_bytes_per_second(HDAAudioStream *st)
static inline uint32_t hda_bytes_per_second(HDAAudioStream *st)
{
return 2LL * st->as.nchannels * st->as.freq;
return 2 * (uint32_t)st->as.nchannels * (uint32_t)st->as.freq;
}
static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos)
@ -222,12 +223,18 @@ static void hda_audio_input_timer(void *opaque)
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int64_t buft_start = st->buft_start;
int64_t uptime = now - st->buft_start;
int64_t wpos = st->wpos;
int64_t rpos = st->rpos;
int64_t wanted_rpos;
int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
/ NANOSECONDS_PER_SECOND;
if (uptime <= 0) {
/* wanted_rpos <= 0 */
goto out_timer;
}
wanted_rpos = muldiv64(uptime, hda_bytes_per_second(st),
NANOSECONDS_PER_SECOND);
wanted_rpos &= -4; /* IMPORTANT! clip to frames */
if (wanted_rpos <= rpos) {
@ -286,12 +293,18 @@ static void hda_audio_output_timer(void *opaque)
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int64_t buft_start = st->buft_start;
int64_t uptime = now - st->buft_start;
int64_t wpos = st->wpos;
int64_t rpos = st->rpos;
int64_t wanted_wpos;
int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
/ NANOSECONDS_PER_SECOND;
if (uptime <= 0) {
/* wanted_wpos <= 0 */
goto out_timer;
}
wanted_wpos = muldiv64(uptime, hda_bytes_per_second(st),
NANOSECONDS_PER_SECOND);
wanted_wpos &= -4; /* IMPORTANT! clip to frames */
if (wanted_wpos <= wpos) {
@ -855,10 +868,10 @@ static Property hda_audio_properties[] = {
static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
const struct desc_codec *desc = &output_nomixemu;
const struct desc_codec *desc = &output_mixemu;
if (!a->mixer) {
desc = &output_mixemu;
desc = &output_nomixemu;
}
hda_audio_init(hda, desc, errp);
@ -867,10 +880,10 @@ static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
const struct desc_codec *desc = &duplex_nomixemu;
const struct desc_codec *desc = &duplex_mixemu;
if (!a->mixer) {
desc = &duplex_mixemu;
desc = &duplex_nomixemu;
}
hda_audio_init(hda, desc, errp);
@ -879,10 +892,10 @@ static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
static void hda_audio_init_micro(HDACodecDevice *hda, Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
const struct desc_codec *desc = &micro_nomixemu;
const struct desc_codec *desc = &micro_mixemu;
if (!a->mixer) {
desc = &micro_mixemu;
desc = &micro_nomixemu;
}
hda_audio_init(hda, desc, errp);

View File

@ -47,12 +47,14 @@ static void virtio_snd_pci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
PCIDeviceClass *pcidevklass = PCI_DEVICE_CLASS(klass);
device_class_set_props(dc, virtio_snd_pci_properties);
dc->desc = "Virtio Sound";
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
vpciklass->realize = virtio_snd_pci_realize;
pcidevklass->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
}
static void virtio_snd_pci_instance_init(Object *obj)

View File

@ -36,6 +36,7 @@ static void virtio_snd_pcm_out_cb(void *data, int available);
static void virtio_snd_process_cmdq(VirtIOSound *s);
static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
static void virtio_snd_pcm_in_cb(void *data, int available);
static void virtio_snd_unrealize(DeviceState *dev);
static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
| BIT(VIRTIO_SND_PCM_FMT_U8)
@ -1065,23 +1066,9 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
virtio_snd_pcm_set_params default_params = { 0 };
uint32_t status;
vsnd->pcm = NULL;
vsnd->vmstate =
qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
trace_virtio_snd_realize(vsnd);
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
vsnd->pcm->snd = vsnd;
vsnd->pcm->streams =
g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
vsnd->pcm->pcm_params =
g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
/* set number of jacks and streams */
/* check number of jacks and streams */
if (vsnd->snd_conf.jacks > 8) {
error_setg(errp,
"Invalid number of jacks: %"PRIu32,
@ -1102,7 +1089,22 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
return;
}
AUD_register_card("virtio-sound", &vsnd->card, errp);
if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) {
return;
}
vsnd->vmstate =
qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
vsnd->pcm->snd = vsnd;
vsnd->pcm->streams =
g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
vsnd->pcm->pcm_params =
g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
/* set default params for all streams */
default_params.features = 0;
@ -1128,16 +1130,21 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
error_setg(errp,
"Can't initialize stream params, device responded with %s.",
print_code(status));
return;
goto error_cleanup;
}
status = virtio_snd_pcm_prepare(vsnd, i);
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
error_setg(errp,
"Can't prepare streams, device responded with %s.",
print_code(status));
return;
goto error_cleanup;
}
}
return;
error_cleanup:
virtio_snd_unrealize(dev);
}
static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,

View File

@ -326,7 +326,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
if (s->connected) {
return 0;
}
s->connected = true;
s->dev.num_queues = s->num_queues;
s->dev.nvqs = s->num_queues;
@ -343,15 +342,14 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
return ret;
}
s->connected = true;
/* restore vhost state */
if (virtio_device_started(vdev, vdev->status)) {
ret = vhost_user_blk_start(vdev, errp);
if (ret < 0) {
return ret;
}
}
return 0;
return ret;
}
static void vhost_user_blk_disconnect(DeviceState *dev)

View File

@ -131,8 +131,12 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
/*
* Can we support APIC ID 255 or higher? With KVM, that requires
* both in-kernel lapic and X2APIC userspace API.
*
* kvm_enabled() must go first to ensure that kvm_* references are
* not emitted for the linker to consume (kvm_enabled() is
* a literal `0` in configurations where kvm_* aren't defined)
*/
if (x86ms->apic_id_limit > 255 && kvm_enabled() &&
if (kvm_enabled() && x86ms->apic_id_limit > 255 &&
(!kvm_irqchip_in_kernel() || !kvm_enable_x2apic())) {
error_report("current -smp configuration requires kernel "
"irqchip and X2APIC API support.");
@ -418,8 +422,13 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
}
cpu->thread_id = topo_ids.smt_id;
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
kvm_enabled() && !kvm_hv_vpindex_settable()) {
/*
* kvm_enabled() must go first to ensure that kvm_* references are
* not emitted for the linker to consume (kvm_enabled() is
* a literal `0` in configurations where kvm_* aren't defined)
*/
if (kvm_enabled() && hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
!kvm_hv_vpindex_settable()) {
error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
return;
}

View File

@ -648,6 +648,7 @@ undo:
}
dev->msix_vector_use_notifier = NULL;
dev->msix_vector_release_notifier = NULL;
dev->msix_vector_poll_notifier = NULL;
return ret;
}

View File

@ -178,7 +178,6 @@ static void register_vfs(PCIDevice *dev)
num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs);
assert(dev->exp.sriov_pf.vf);
trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), num_vfs);

View File

@ -147,7 +147,6 @@ static int vhost_user_scsi_connect(DeviceState *dev, Error **errp)
if (s->connected) {
return 0;
}
s->connected = true;
vsc->dev.num_queues = vs->conf.num_queues;
vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
@ -161,6 +160,8 @@ static int vhost_user_scsi_connect(DeviceState *dev, Error **errp)
return ret;
}
s->connected = true;
/* restore vhost state */
if (virtio_device_started(vdev, vdev->status)) {
ret = vhost_user_scsi_start(s, errp);
@ -359,6 +360,20 @@ static Property vhost_user_scsi_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static void vhost_user_scsi_reset(VirtIODevice *vdev)
{
VHostUserSCSI *s = VHOST_USER_SCSI(vdev);
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
vhost_dev_free_inflight(vsc->inflight);
}
static struct vhost_dev *vhost_user_scsi_get_vhost(VirtIODevice *vdev)
{
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(vdev);
return &vsc->dev;
}
static const VMStateDescription vmstate_vhost_scsi = {
.name = "virtio-scsi",
.minimum_version_id = 1,
@ -384,6 +399,8 @@ static void vhost_user_scsi_class_init(ObjectClass *klass, void *data)
vdc->set_config = vhost_scsi_common_set_config;
vdc->set_status = vhost_user_scsi_set_status;
fwc->get_dev_path = vhost_scsi_common_get_fw_dev_path;
vdc->reset = vhost_user_scsi_reset;
vdc->get_vhost = vhost_user_scsi_get_vhost;
}
static void vhost_user_scsi_instance_init(Object *obj)

View File

@ -229,7 +229,6 @@ static int vu_gpio_connect(DeviceState *dev, Error **errp)
if (gpio->connected) {
return 0;
}
gpio->connected = true;
vhost_dev_set_config_notifier(vhost_dev, &gpio_ops);
gpio->vhost_user.supports_config = true;
@ -243,6 +242,8 @@ static int vu_gpio_connect(DeviceState *dev, Error **errp)
return ret;
}
gpio->connected = true;
/* restore vhost state */
if (virtio_device_started(vdev, vdev->status)) {
vu_gpio_start(vdev);

View File

@ -698,9 +698,6 @@ static int virtio_iommu_probe(VirtIOIOMMU *s,
}
sdev = container_of(iommu_mr, IOMMUDevice, iommu_mr);
if (!sdev) {
return -EINVAL;
}
count = virtio_iommu_fill_resv_mem_prop(sdev, ep_id, buf, free);
if (count < 0) {

View File

@ -2137,7 +2137,7 @@ void virtio_reset(void *opaque)
vdev->device_endian = virtio_default_endian();
}
if (vdev->vhost_started) {
if (vdev->vhost_started && k->get_vhost) {
vhost_reset_device(k->get_vhost(vdev));
}

View File

@ -779,6 +779,16 @@ static inline int platform_does_not_support_system(const char *command)
}
#endif /* !HAVE_SYSTEM_FUNCTION */
/**
* If the load average was unobtainable, -1 is returned
*/
#ifndef HAVE_GETLOADAVG_FUNCTION
static inline int getloadavg(double loadavg[], int nelem)
{
return -1;
}
#endif /* !HAVE_GETLOADAVG_FUNCTION */
#ifdef __cplusplus
}
#endif

View File

@ -2293,6 +2293,7 @@ config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
config_host_data.set('HAVE_GETLOADAVG_FUNCTION', cc.has_function('getloadavg', prefix: '#include <stdlib.h>'))
if rbd.found()
config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
cc.has_function('rbd_namespace_exists',

View File

@ -112,6 +112,7 @@ static const char *iasl;
#endif
static int verbosity_level;
static GArray *load_expected_aml(test_data *data);
static bool compare_signature(const AcpiSdtTable *sdt, const char *signature)
{
@ -244,21 +245,32 @@ static void test_acpi_fadt_table(test_data *data)
static void dump_aml_files(test_data *data, bool rebuild)
{
AcpiSdtTable *sdt;
AcpiSdtTable *sdt, *exp_sdt;
GError *error = NULL;
gchar *aml_file = NULL;
test_data exp_data = {};
gint fd;
ssize_t ret;
int i;
exp_data.tables = load_expected_aml(data);
for (i = 0; i < data->tables->len; ++i) {
const char *ext = data->variant ? data->variant : "";
sdt = &g_array_index(data->tables, AcpiSdtTable, i);
exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
g_assert(sdt->aml);
g_assert(exp_sdt->aml);
if (rebuild) {
aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
sdt->aml, ext);
if (!g_file_test(aml_file, G_FILE_TEST_EXISTS) &&
sdt->aml_len == exp_sdt->aml_len &&
!memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) {
/* identical tables, no need to write new files */
g_free(aml_file);
continue;
}
fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
if (fd < 0) {

View File

@ -18,6 +18,32 @@
#define CONNECTION_TIMEOUT 120
static double connection_timeout(void)
{
double load;
int ret = getloadavg(&load, 1);
/*
* If we can't get load data, or load is low because we just started
* running, assume load of 1 (we are alone in this system).
*/
if (ret < 1 || load < 1.0) {
load = 1.0;
}
/*
* No one wants to wait more than 10 minutes for this test. Higher load?
* Too bad.
*/
if (load > 10.0) {
fprintf(stderr, "Warning: load %f higher than 10 - test might timeout\n",
load);
load = 10.0;
}
/* if load is high increase timeout as we might not get a chance to run */
return load * CONNECTION_TIMEOUT;
}
#define EXPECT_STATE(q, e, t) \
do { \
char *resp = NULL; \
@ -31,7 +57,7 @@ do { \
if (g_str_equal(resp, e)) { \
break; \
} \
} while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \
} while (g_test_timer_elapsed() < connection_timeout()); \
g_assert_cmpstr(resp, ==, e); \
g_free(resp); \
} while (0)