* add host ticks function for RISC-V

* target/i386: Export GDS_NO bit
 * target/i386: add support for bit 56 of MSR_IA32_VMX_BASIC
 * first part of audiodev cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmUNtYUUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroN7Uwf9Fy4aE1PHzSNr2FqT4rUSYrT4N8cL
 QiPeB8JiJUnl73TcCkTwi7S/Az+37okv+Qsr7eh1wdarY8DOYir9dGJU3TGzICSw
 cgPImb99rhBc2kEmwciCWGlhXIMD8WNN64EanPPg5VeQYdzrorYwl7jCTMQMBR5H
 wtOq3f6FfYJonVwZ6YOmbioD2mFfoGBuiDcYmTTw440vrruKqHagbm5onD1SY9kR
 SM0/HXcYaKB6Ae9qNKhyR9h94KZzDUkCvcTLdFGtK90GBs4VxZVHQn6Dpkh5lPtT
 t0MbMv1mcO6ODzg9TxO3gUAgoklTy3gM2wISXo5C9NGuxmF2svwkuQl5pg==
 =CuIa
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* add host ticks function for RISC-V
* target/i386: Export GDS_NO bit
* target/i386: add support for bit 56 of MSR_IA32_VMX_BASIC
* first part of audiodev cleanups

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmUNtYUUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroN7Uwf9Fy4aE1PHzSNr2FqT4rUSYrT4N8cL
# QiPeB8JiJUnl73TcCkTwi7S/Az+37okv+Qsr7eh1wdarY8DOYir9dGJU3TGzICSw
# cgPImb99rhBc2kEmwciCWGlhXIMD8WNN64EanPPg5VeQYdzrorYwl7jCTMQMBR5H
# wtOq3f6FfYJonVwZ6YOmbioD2mFfoGBuiDcYmTTw440vrruKqHagbm5onD1SY9kR
# SM0/HXcYaKB6Ae9qNKhyR9h94KZzDUkCvcTLdFGtK90GBs4VxZVHQn6Dpkh5lPtT
# t0MbMv1mcO6ODzg9TxO3gUAgoklTy3gM2wISXo5C9NGuxmF2svwkuQl5pg==
# =CuIa
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 22 Sep 2023 11:40:53 EDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu:
  vl: recognize audiodev groups in configuration files
  tests/qtest: Specify audiodev= and -audiodev
  hw/display/xlnx_dp.c: Add audiodev property
  hw/audio/lm4549: Add errp error reporting to init function
  hw/audio: Simplify hda audio init
  hw/input/tsc210x: Extract common init code into new function
  qemu/timer: Add host ticks function for RISC-V
  target/i386: Export GDS_NO bit to guests
  target/i386: enumerate bit 56 of MSR_IA32_VMX_BASIC

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-09-25 10:09:38 -04:00
commit 29578f5757
18 changed files with 115 additions and 74 deletions

View File

@ -288,3 +288,7 @@
driver = "hda-duplex"
bus = "ich9-hda-audio.0"
cad = "0"
audiodev = "audiodev0"
[audiodev "audiodev0"]
driver = "none" # CHANGE ME

View File

@ -248,3 +248,7 @@
driver = "hda-duplex"
bus = "sound.0"
cad = "0"
audiodev = "audiodev0"
[audiodev "audiodev0"]
driver = "none" # CHANGE ME

View File

@ -675,7 +675,9 @@ static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, b
}
}
static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
static void hda_audio_init(HDACodecDevice *hda,
const struct desc_codec *desc,
Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
HDAAudioStream *st;
@ -718,7 +720,6 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
break;
}
}
return 0;
}
static void hda_audio_exit(HDACodecDevice *hda)
@ -848,37 +849,40 @@ static Property hda_audio_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static int hda_audio_init_output(HDACodecDevice *hda)
static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
const struct desc_codec *desc = &output_nomixemu;
if (!a->mixer) {
return hda_audio_init(hda, &output_nomixemu);
} else {
return hda_audio_init(hda, &output_mixemu);
desc = &output_mixemu;
}
hda_audio_init(hda, desc, errp);
}
static int hda_audio_init_duplex(HDACodecDevice *hda)
static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
const struct desc_codec *desc = &duplex_nomixemu;
if (!a->mixer) {
return hda_audio_init(hda, &duplex_nomixemu);
} else {
return hda_audio_init(hda, &duplex_mixemu);
desc = &duplex_mixemu;
}
hda_audio_init(hda, desc, errp);
}
static int hda_audio_init_micro(HDACodecDevice *hda)
static void hda_audio_init_micro(HDACodecDevice *hda, Error **errp)
{
HDAAudioState *a = HDA_AUDIO(hda);
const struct desc_codec *desc = &micro_nomixemu;
if (!a->mixer) {
return hda_audio_init(hda, &micro_nomixemu);
} else {
return hda_audio_init(hda, &micro_mixemu);
desc = &micro_mixemu;
}
hda_audio_init(hda, desc, errp);
}
static void hda_audio_base_class_init(ObjectClass *klass, void *data)

View File

@ -71,9 +71,7 @@ static void hda_codec_dev_realize(DeviceState *qdev, Error **errp)
return;
}
bus->next_cad = dev->cad + 1;
if (cdc->init(dev) != 0) {
error_setg(errp, "HDA audio init failed");
}
cdc->init(dev, errp);
}
static void hda_codec_dev_unrealize(DeviceState *qdev)

View File

@ -31,7 +31,7 @@ struct HDACodecBus {
struct HDACodecDeviceClass {
DeviceClass parent_class;
int (*init)(HDACodecDevice *dev);
void (*init)(HDACodecDevice *dev, Error **errp);
void (*exit)(HDACodecDevice *dev);
void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output);

View File

@ -276,7 +276,8 @@ static int lm4549_post_load(void *opaque, int version_id)
return 0;
}
void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque)
void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque,
Error **errp)
{
struct audsettings as;

View File

@ -36,7 +36,8 @@ typedef struct {
extern const VMStateDescription vmstate_lm4549_state;
void lm4549_init(lm4549_state *s, lm4549_callback data_req, void *opaque);
void lm4549_init(lm4549_state *s, lm4549_callback data_req, void *opaque,
Error **errp);
uint32_t lm4549_read(lm4549_state *s, hwaddr offset);
void lm4549_write(lm4549_state *s, hwaddr offset, uint32_t value);
uint32_t lm4549_write_samples(lm4549_state *s, uint32_t left, uint32_t right);

View File

@ -564,7 +564,7 @@ static void pl041_realize(DeviceState *dev, Error **errp)
}
/* Init the codec */
lm4549_init(&s->codec, &pl041_request_data, (void *)s);
lm4549_init(&s->codec, &pl041_request_data, (void *)s, errp);
}
static const VMStateDescription vmstate_pl041_regfile = {

View File

@ -1385,6 +1385,11 @@ static void xlnx_dp_reset(DeviceState *dev)
xlnx_dp_update_irq(s);
}
static Property xlnx_dp_device_properties[] = {
DEFINE_AUDIO_PROPERTIES(XlnxDPState, aud_card),
DEFINE_PROP_END_OF_LIST(),
};
static void xlnx_dp_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@ -1392,6 +1397,7 @@ static void xlnx_dp_class_init(ObjectClass *oc, void *data)
dc->realize = xlnx_dp_realize;
dc->vmsd = &vmstate_dp;
dc->reset = xlnx_dp_reset;
device_class_set_props(dc, xlnx_dp_device_properties);
}
static const TypeInfo xlnx_dp_info = {

View File

@ -30,6 +30,7 @@
#include "hw/input/tsc2xxx.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "qapi/error.h"
#define TSC_DATA_REGISTERS_PAGE 0x0
#define TSC_CONTROL_REGISTERS_PAGE 0x1
@ -1069,20 +1070,10 @@ static const VMStateDescription vmstate_tsc2301 = {
.fields = vmstatefields_tsc210x,
};
uWireSlave *tsc2102_init(qemu_irq pint)
static void tsc210x_init(TSC210xState *s,
const char *name,
const VMStateDescription *vmsd)
{
TSC210xState *s;
s = g_new0(TSC210xState, 1);
s->x = 160;
s->y = 160;
s->pressure = 0;
s->precision = s->nextprecision = 0;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc210x_timer_tick, s);
s->pint = pint;
s->model = 0x2102;
s->name = "tsc2102";
s->tr[0] = 0;
s->tr[1] = 1;
s->tr[2] = 1;
@ -1104,13 +1095,29 @@ uWireSlave *tsc2102_init(qemu_irq pint)
tsc210x_reset(s);
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
"QEMU TSC2102-driven Touchscreen");
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1, name);
AUD_register_card(s->name, &s->card);
qemu_register_reset((void *) tsc210x_reset, s);
vmstate_register(NULL, 0, &vmstate_tsc2102, s);
vmstate_register(NULL, 0, vmsd, s);
}
uWireSlave *tsc2102_init(qemu_irq pint)
{
TSC210xState *s;
s = g_new0(TSC210xState, 1);
s->x = 160;
s->y = 160;
s->pressure = 0;
s->precision = s->nextprecision = 0;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc210x_timer_tick, s);
s->pint = pint;
s->model = 0x2102;
s->name = "tsc2102";
tsc210x_init(s, "QEMU TSC2102-driven Touchscreen", &vmstate_tsc2102);
return &s->chip;
}
@ -1131,34 +1138,7 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
s->model = 0x2301;
s->name = "tsc2301";
s->tr[0] = 0;
s->tr[1] = 1;
s->tr[2] = 1;
s->tr[3] = 0;
s->tr[4] = 1;
s->tr[5] = 0;
s->tr[6] = 1;
s->tr[7] = 0;
s->chip.opaque = s;
s->chip.send = (void *) tsc210x_write;
s->chip.receive = (void *) tsc210x_read;
s->codec.opaque = s;
s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
s->codec.in.fifo = s->in_fifo;
s->codec.out.fifo = s->out_fifo;
tsc210x_reset(s);
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
"QEMU TSC2301-driven Touchscreen");
AUD_register_card(s->name, &s->card);
qemu_register_reset((void *) tsc210x_reset, s);
vmstate_register(NULL, 0, &vmstate_tsc2301, s);
tsc210x_init(s, "QEMU TSC2301-driven Touchscreen", &vmstate_tsc2301);
return &s->chip;
}

View File

@ -979,6 +979,28 @@ static inline int64_t cpu_get_host_ticks(void)
return cur - ofs;
}
#elif defined(__riscv) && __riscv_xlen == 32
static inline int64_t cpu_get_host_ticks(void)
{
uint32_t lo, hi, tmph;
do {
asm volatile("RDTIMEH %0\n\t"
"RDTIME %1\n\t"
"RDTIMEH %2"
: "=r"(hi), "=r"(lo), "=r"(tmph));
} while (unlikely(tmph != hi));
return lo | (uint64_t)hi << 32;
}
#elif defined(__riscv) && __riscv_xlen > 32
static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile("RDTIME %0" : "=r"(val));
return val;
}
#else
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be

View File

@ -115,6 +115,7 @@ controls = [
(50, 53): 'VMCS memory type',
54: 'INS/OUTS instruction information',
55: 'IA32_VMX_TRUE_*_CTLS support',
56: 'Skip checks on event error code',
},
msr = MSR_IA32_VMX_BASIC,
),

View File

@ -2125,6 +2125,7 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
static bool is_qemuopts_group(const char *group)
{
if (g_str_equal(group, "object") ||
g_str_equal(group, "audiodev") ||
g_str_equal(group, "machine") ||
g_str_equal(group, "smp-opts") ||
g_str_equal(group, "boot-opts")) {
@ -2140,6 +2141,15 @@ static void qemu_record_config_group(const char *group, QDict *dict,
Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict));
object_option_add_visitor(v);
visit_free(v);
} else if (g_str_equal(group, "audiodev")) {
Audiodev *dev = NULL;
Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict));
if (visit_type_Audiodev(v, NULL, &dev, errp)) {
audio_define(dev);
}
visit_free(v);
} else if (g_str_equal(group, "machine")) {
/*
* Cannot merge string-valued and type-safe dictionaries, so JSON

View File

@ -1155,7 +1155,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
NULL, "sbdr-ssdp-no", "fbsdp-no", "psdp-no",
NULL, "fb-clear", NULL, NULL,
NULL, NULL, NULL, NULL,
"pbrsb-no", NULL, NULL, NULL,
"pbrsb-no", NULL, "gds-no", NULL,
NULL, NULL, NULL, NULL,
},
.msr = {
@ -1340,6 +1340,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.feat_names = {
[54] = "vmx-ins-outs",
[55] = "vmx-true-ctls",
[56] = "vmx-any-errcode",
},
.msr = {
.index = MSR_IA32_VMX_BASIC,

View File

@ -1039,6 +1039,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define MSR_VMX_BASIC_DUAL_MONITOR (1ULL << 49)
#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54)
#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55)
#define MSR_VMX_BASIC_ANY_ERRCODE (1ULL << 56)
#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full
#define MSR_VMX_MISC_STORE_LMA (1ULL << 5)

View File

@ -46,7 +46,8 @@ static void *es1370_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
static void es1370_register_nodes(void)
{
QOSGraphEdgeOptions opts = {
.extra_device_opts = "addr=04.0",
.extra_device_opts = "addr=04.0,audiodev=audio0",
.before_cmd_line = "-audiodev driver=none,id=audio0",
};
add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) });

View File

@ -106,8 +106,10 @@ const generic_fuzz_config predefined_configs[] = {
},{
.name = "intel-hda",
.args = "-machine q35 -nodefaults -device intel-hda,id=hda0 "
"-device hda-output,bus=hda0.0 -device hda-micro,bus=hda0.0 "
"-device hda-duplex,bus=hda0.0",
"-audiodev driver=none,id=audio0",
"-device hda-output,bus=hda0.0,audiodev=audio0 "
"-device hda-micro,bus=hda0.0,audiodev=audio0 "
"-device hda-duplex,bus=hda0.0,audiodev=audio0",
.objects = "intel-hda",
},{
.name = "ide-hd",

View File

@ -11,20 +11,24 @@
#include "libqtest-single.h"
#define HDA_ID "hda0"
#define CODEC_DEVICES " -device hda-output,bus=" HDA_ID ".0" \
" -device hda-micro,bus=" HDA_ID ".0" \
" -device hda-duplex,bus=" HDA_ID ".0"
#define AUDIODEV " -audiodev driver=none,id=audio0 "
#define AUDIODEV_REF "audiodev=audio0"
#define CODEC_DEVICES " -device hda-output,bus=" HDA_ID ".0," AUDIODEV_REF \
" -device hda-micro,bus=" HDA_ID ".0," AUDIODEV_REF \
" -device hda-duplex,bus=" HDA_ID ".0," AUDIODEV_REF
/* Tests only initialization so far. TODO: Replace with functional tests */
static void ich6_test(void)
{
qtest_start("-machine pc -device intel-hda,id=" HDA_ID CODEC_DEVICES);
qtest_start(AUDIODEV "-machine pc -device intel-hda,id=" HDA_ID CODEC_DEVICES);
qtest_end();
}
static void ich9_test(void)
{
qtest_start("-machine q35 -device ich9-intel-hda,bus=pcie.0,addr=1b.0,id="
qtest_start("-machine q35"
AUDIODEV
"-device ich9-intel-hda,bus=pcie.0,addr=1b.0,id="
HDA_ID CODEC_DEVICES);
qtest_end();
}
@ -39,6 +43,7 @@ static void test_issue542_ich6(void)
QTestState *s;
s = qtest_init("-nographic -nodefaults -M pc-q35-6.2 "
AUDIODEV
"-device intel-hda,id=" HDA_ID CODEC_DEVICES);
qtest_outl(s, 0xcf8, 0x80000804);