From nobody Fri May 10 08:16:43 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1620901340; cv=none; d=zohomail.com; s=zohoarc; b=RcxpRM3mqAm8ysgCBUJh4n6lUEQ6VbjszQxBzD7kKodyhWE114T0WIANjTONfXOfhvGok8hyZuMfBw54lzYBubg50WcSD/c5q3idotjuzn/vFXjFcWHT//3CVNz203TkzFXOVvzXrX/6HjNhueoMY5U1OsFo1wbsAM/WgyaSDaI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1620901340; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=CazH+h+iKHF1CLDHVel/3b3SMm1kIbly/FGDZLcRMos=; b=LJCEKdrCUGMhJbatoo0Bf82DE9Lo2EiQ2e88AhMpN010/b+WHNOeZmU12SePiVX22Afv8XYlMQy8AkvJsaoyKXDiphoBQhGrlsIl7jfJe5pzCX5RycpvM1XuSoPVZdOIy8BRD8tVGP7x114mGQa9cKq+aptbrE9KHzq1lGfkiqI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1620901340264574.4455602649226; Thu, 13 May 2021 03:22:20 -0700 (PDT) Received: from localhost ([::1]:45752 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lh8Tz-0004hE-2a for importer@patchew.org; Thu, 13 May 2021 06:22:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57122) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lh8JH-0004u1-6W for qemu-devel@nongnu.org; Thu, 13 May 2021 06:11:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:55962) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lh8J9-0006iV-Pd for qemu-devel@nongnu.org; Thu, 13 May 2021 06:11:14 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-161-T9POf_OMMAiCa5yDIcucOg-1; Thu, 13 May 2021 06:11:04 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 88D2CFC93 for ; Thu, 13 May 2021 10:11:03 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 47AC060CC6; Thu, 13 May 2021 10:11:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1620900666; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CazH+h+iKHF1CLDHVel/3b3SMm1kIbly/FGDZLcRMos=; b=T3mE81MJO0OVSHAL2+NTg59i6fx8cv41OsNvuz1PgHLJXGOcUk4d5JE/1ROxaqiEqRHG67 cpAvAOFk3v6NsQco56hClOCw9O5abSP91vaWtjdp3hnXjs5y8kBYFscg2fuiqLMsxN+RMy LVZkwM7lwqkt6rTSeiK7bTluSznhBqg= X-MC-Unique: T9POf_OMMAiCa5yDIcucOg-1 From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH] qtest: add a QOM object for qtest Date: Thu, 13 May 2021 06:11:02 -0400 Message-Id: <20210513101102.928331-1-pbonzini@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=pbonzini@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.7, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: thuth@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The qtest server right now can only be created using the -qtest and -qtest-log options. Allow an alternative way to create it using "-object qtest,chardev=3D...,log=3D...". This is part of the long term plan to make more (or all) of QEMU configurable through QMP and preconfig mode. Signed-off-by: Paolo Bonzini --- qapi/qom.json | 17 +++++ softmmu/qtest.c | 185 +++++++++++++++++++++++++++++++++++++++++++++--- softmmu/vl.c | 5 +- 3 files changed, 196 insertions(+), 11 deletions(-) diff --git a/qapi/qom.json b/qapi/qom.json index f1e243dbe5..bcb7e6ba51 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -644,6 +644,21 @@ { 'struct': 'PrManagerHelperProperties', 'data': { 'path': 'str' } } =20 +## +# @QtestProperties: +# +# Properties for qtest objects. +# +# @chardev: the chardev to be used to receive qtest commands on. +# +# @log: the path to a log file +# +# Since: 6.0 +## +{ 'struct': 'QtestProperties', + 'data': { 'chardev': 'str', + '*log': 'str' } } + ## # @RemoteObjectProperties: # @@ -769,6 +784,7 @@ 'memory-backend-ram', 'pef-guest', 'pr-manager-helper', + 'qtest', 'rng-builtin', 'rng-egd', 'rng-random', @@ -825,6 +841,7 @@ 'if': 'defined(CONFIG_LINUX)' }, 'memory-backend-ram': 'MemoryBackendProperties', 'pr-manager-helper': 'PrManagerHelperProperties', + 'qtest': 'QtestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': 'RngRandomProperties', diff --git a/softmmu/qtest.c b/softmmu/qtest.c index 130c366615..4728c2da53 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -27,6 +27,8 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/cutils.h" +#include "qapi/qmp/qerror.h" +#include "qom/object_interfaces.h" #include CONFIG_DEVICES #ifdef CONFIG_PSERIES #include "hw/ppc/spapr_rtas.h" @@ -34,11 +36,25 @@ =20 #define MAX_IRQ 256 =20 +#define TYPE_QTEST "qtest" + +OBJECT_DECLARE_SIMPLE_TYPE(QTest, QTEST) + +struct QTest { + Object parent; + + bool has_machine_link; + char *chr_name; + Chardev *chr; + CharBackend qtest_chr; + char *log; +}; + bool qtest_allowed; =20 static DeviceState *irq_intercept_dev; static FILE *qtest_log_fp; -static CharBackend qtest_chr; +static QTest *qtest; static GString *inbuf; static int irq_levels[MAX_IRQ]; static qemu_timeval start_time; @@ -320,7 +336,7 @@ static void qtest_irq_handler(void *opaque, int n, int = level) qemu_set_irq(old_irq, level); =20 if (irq_levels[n] !=3D level) { - CharBackend *chr =3D &qtest_chr; + CharBackend *chr =3D &qtest->qtest_chr; irq_levels[n] =3D level; qtest_send_prefix(chr); qtest_sendf(chr, "IRQ %s %d\n", @@ -849,18 +865,39 @@ static void qtest_event(void *opaque, QEMUChrEvent ev= ent) break; } } + void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Er= ror **errp) { + ERRP_GUARD(); Chardev *chr; + Object *qtest; =20 chr =3D qemu_chr_new("qtest", qtest_chrdev, NULL); - if (chr =3D=3D NULL) { error_setg(errp, "Failed to initialize device for qtest: \"%s\"", qtest_chrdev); return; } =20 + qtest =3D object_new(TYPE_QTEST); + object_property_set_str(qtest, "chardev", "qtest", &error_abort); + if (qtest_log) { + object_property_set_str(qtest, "log", qtest_log, &error_abort); + } + object_property_add_child(qdev_get_machine(), "qtest", qtest); + user_creatable_complete(USER_CREATABLE(qtest), errp); + if (*errp) { + object_unparent(qtest); + } + object_unref(OBJECT(chr)); + object_unref(qtest); +} + +static bool qtest_server_start(QTest *q, Error **errp) +{ + Chardev *chr =3D q->chr; + const char *qtest_log =3D q->log; + if (qtest_log) { if (strcmp(qtest_log, "none") !=3D 0) { qtest_log_fp =3D fopen(qtest_log, "w+"); @@ -869,16 +906,20 @@ void qtest_server_init(const char *qtest_chrdev, cons= t char *qtest_log, Error ** qtest_log_fp =3D stderr; } =20 - qemu_chr_fe_init(&qtest_chr, chr, errp); - qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read, - qtest_event, NULL, &qtest_chr, NULL, true); - qemu_chr_fe_set_echo(&qtest_chr, true); + if (!qemu_chr_fe_init(&q->qtest_chr, chr, errp)) { + return false; + } + qemu_chr_fe_set_handlers(&q->qtest_chr, qtest_can_read, qtest_read, + qtest_event, NULL, &q->qtest_chr, NULL, true); + qemu_chr_fe_set_echo(&q->qtest_chr, true); =20 inbuf =3D g_string_new(""); =20 if (!qtest_server_send) { - qtest_server_set_send_handler(qtest_server_char_be_send, &qtest_ch= r); + qtest_server_set_send_handler(qtest_server_char_be_send, &q->qtest= _chr); } + qtest =3D q; + return true; } =20 void qtest_server_set_send_handler(void (*send)(void*, const char*), @@ -890,7 +931,7 @@ void qtest_server_set_send_handler(void (*send)(void*, = const char*), =20 bool qtest_driver(void) { - return qtest_chr.chr !=3D NULL; + return qtest->qtest_chr.chr !=3D NULL; } =20 void qtest_server_inproc_recv(void *dummy, const char *buf) @@ -905,3 +946,129 @@ void qtest_server_inproc_recv(void *dummy, const char= *buf) g_string_truncate(gstr, 0); } } + +static void qtest_complete(UserCreatable *uc, Error **errp) +{ + QTest *q =3D QTEST(uc); + if (qtest) { + error_setg(errp, "Only one instance of qtest can be created"); + return; + } + if (!q->chr_name) { + error_setg(errp, "No backend specified"); + return; + } + + if (OBJECT(uc)->parent !=3D qdev_get_machine()) { + q->has_machine_link =3D true; + object_property_add_const_link(qdev_get_machine(), "qtest", OBJECT= (uc)); + } else { + /* -qtest was used. */ + } + + qtest_server_start(q, errp); +} + +static void qtest_unparent(Object *obj) +{ + QTest *q =3D QTEST(obj); + + if (qtest =3D=3D q) { + qemu_chr_fe_disconnect(&q->qtest_chr); + assert(!qtest_opened); + qemu_chr_fe_deinit(&q->qtest_chr, false); + if (qtest_log_fp) { + fclose(qtest_log_fp); + qtest_log_fp =3D NULL; + } + qtest =3D NULL; + } + + if (q->has_machine_link) { + object_property_del(qdev_get_machine(), "qtest"); + q->has_machine_link =3D false; + } +} + +static void qtest_set_log(Object *obj, const char *value, Error **errp) +{ + QTest *q =3D QTEST(obj); + + if (qtest =3D=3D q) { + error_setg(errp, QERR_PERMISSION_DENIED); + } else { + g_free(q->log); + q->log =3D g_strdup(value); + } +} + +static char *qtest_get_log(Object *obj, Error **errp) +{ + QTest *q =3D QTEST(obj); + + return g_strdup(q->log); +} + +static void qtest_set_chardev(Object *obj, const char *value, Error **errp) +{ + QTest *q =3D QTEST(obj); + Chardev *chr; + + if (qtest =3D=3D q) { + error_setg(errp, QERR_PERMISSION_DENIED); + return; + } + + chr =3D qemu_chr_find(value); + if (!chr) { + error_setg(errp, "Cannot find character device '%s'", value); + return; + } + + g_free(q->chr_name); + q->chr_name =3D g_strdup(value); + + if (q->chr) { + object_unref(q->chr); + } + q->chr =3D chr; + object_ref(chr); +} + +static char *qtest_get_chardev(Object *obj, Error **errp) +{ + QTest *q =3D QTEST(obj); + + return g_strdup(q->chr_name); +} + +static void qtest_class_init(ObjectClass *oc, void *data) +{ + UserCreatableClass *ucc =3D USER_CREATABLE_CLASS(oc); + + oc->unparent =3D qtest_unparent; + ucc->complete =3D qtest_complete; + + object_class_property_add_str(oc, "chardev", + qtest_get_chardev, qtest_set_chardev); + object_class_property_add_str(oc, "log", + qtest_get_log, qtest_set_log); +} + +static const TypeInfo qtest_info =3D { + .name =3D TYPE_QTEST, + .parent =3D TYPE_OBJECT, + .class_init =3D qtest_class_init, + .instance_size =3D sizeof(QTest), + .interfaces =3D (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + +static void register_types(void) +{ + type_register_static(&qtest_info); +} + +type_init(register_types); diff --git a/softmmu/vl.c b/softmmu/vl.c index 93e78469bc..11ac3750d8 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1758,8 +1758,9 @@ static bool object_create_early(const char *type) * add one, state the reason in a comment! */ =20 - /* Reason: rng-egd property "chardev" */ - if (g_str_equal(type, "rng-egd")) { + /* Reason: property "chardev" */ + if (g_str_equal(type, "rng-egd") || + g_str_equal(type, "qtest")) { return false; } =20 --=20 2.26.2