From f9be4771d3bdfaa8ace096e03c38f6b538ff6d85 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 14 Mar 2023 18:30:09 +0100 Subject: [PATCH 01/23] hw: Add compat machines for 8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 8.1 machine types for arm/i440fx/m68k/q35/s390x/spapr. Signed-off-by: Cornelia Huck Message-Id: <20230314173009.152667-1-cohuck@redhat.com> Reviewed-by: Cédric Le Goater Reviewed-by: Thomas Huth Acked-by: Gavin Shan Signed-off-by: Thomas Huth --- hw/arm/virt.c | 11 +++++++++-- hw/core/machine.c | 3 +++ hw/i386/pc.c | 3 +++ hw/i386/pc_piix.c | 16 +++++++++++++--- hw/i386/pc_q35.c | 14 ++++++++++++-- hw/m68k/virt.c | 11 +++++++++-- hw/ppc/spapr.c | 17 ++++++++++++++--- hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++- include/hw/boards.h | 3 +++ include/hw/i386/pc.h | 3 +++ 10 files changed, 82 insertions(+), 13 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index ac626b3bef..267fe56fae 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3232,10 +3232,17 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); -static void virt_machine_8_0_options(MachineClass *mc) +static void virt_machine_8_1_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE_AS_LATEST(8, 0) +DEFINE_VIRT_MACHINE_AS_LATEST(8, 1) + +static void virt_machine_8_0_options(MachineClass *mc) +{ + virt_machine_8_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len); +} +DEFINE_VIRT_MACHINE(8, 0) static void virt_machine_7_2_options(MachineClass *mc) { diff --git a/hw/core/machine.c b/hw/core/machine.c index cd13b8b0a3..2ce97a5d3b 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -39,6 +39,9 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" +GlobalProperty hw_compat_8_0[] = {}; +const size_t hw_compat_8_0_len = G_N_ELEMENTS(hw_compat_8_0); + GlobalProperty hw_compat_7_2[] = { { "e1000e", "migrate-timadj", "off" }, { "virtio-mem", "x-early-migration", "false" }, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1489abf010..615e1d3d06 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -116,6 +116,9 @@ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, +GlobalProperty pc_compat_8_0[] = {}; +const size_t pc_compat_8_0_len = G_N_ELEMENTS(pc_compat_8_0); + GlobalProperty pc_compat_7_2[] = { { "ICH9-LPC", "noreboot", "true" }, }; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 30eedd62a3..21591dad8d 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -454,21 +454,31 @@ static void pc_i440fx_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } -static void pc_i440fx_8_0_machine_options(MachineClass *m) +static void pc_i440fx_8_1_machine_options(MachineClass *m) { pc_i440fx_machine_options(m); m->alias = "pc"; m->is_default = true; } +DEFINE_I440FX_MACHINE(v8_1, "pc-i440fx-8.1", NULL, + pc_i440fx_8_1_machine_options); + +static void pc_i440fx_8_0_machine_options(MachineClass *m) +{ + pc_i440fx_8_1_machine_options(m); + m->alias = NULL; + m->is_default = false; + compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len); + compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len); +} + DEFINE_I440FX_MACHINE(v8_0, "pc-i440fx-8.0", NULL, pc_i440fx_8_0_machine_options); static void pc_i440fx_7_2_machine_options(MachineClass *m) { pc_i440fx_8_0_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len); compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 797ba347fd..f02919d92c 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -373,19 +373,29 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } -static void pc_q35_8_0_machine_options(MachineClass *m) +static void pc_q35_8_1_machine_options(MachineClass *m) { pc_q35_machine_options(m); m->alias = "q35"; } +DEFINE_Q35_MACHINE(v8_1, "pc-q35-8.1", NULL, + pc_q35_8_1_machine_options); + +static void pc_q35_8_0_machine_options(MachineClass *m) +{ + pc_q35_8_1_machine_options(m); + m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len); + compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len); +} + DEFINE_Q35_MACHINE(v8_0, "pc-q35-8.0", NULL, pc_q35_8_0_machine_options); static void pc_q35_7_2_machine_options(MachineClass *m) { pc_q35_8_0_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len); compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len); } diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 754b9bdfcc..731205b215 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -347,10 +347,17 @@ type_init(virt_machine_register_types) } \ type_init(machvirt_machine_##major##_##minor##_init); -static void virt_machine_8_0_options(MachineClass *mc) +static void virt_machine_8_1_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE(8, 0, true) +DEFINE_VIRT_MACHINE(8, 1, true) + +static void virt_machine_8_0_options(MachineClass *mc) +{ + virt_machine_8_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len); +} +DEFINE_VIRT_MACHINE(8, 0, false) static void virt_machine_7_2_options(MachineClass *mc) { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4921198b9d..ddc9c7b1a1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4735,14 +4735,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc) type_init(spapr_machine_register_##suffix) /* - * pseries-8.0 + * pseries-8.1 */ -static void spapr_machine_8_0_class_options(MachineClass *mc) +static void spapr_machine_8_1_class_options(MachineClass *mc) { /* Defaults for the latest behaviour inherited from the base class */ } -DEFINE_SPAPR_MACHINE(8_0, "8.0", true); +DEFINE_SPAPR_MACHINE(8_1, "8.1", true); + +/* + * pseries-8.0 + */ +static void spapr_machine_8_0_class_options(MachineClass *mc) +{ + spapr_machine_8_1_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len); +} + +DEFINE_SPAPR_MACHINE(8_0, "8.0", false); /* * pseries-7.2 diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 503f212a31..e6f2c62625 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -826,14 +826,26 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +static void ccw_machine_8_1_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_8_1_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(8_1, "8.1", true); + static void ccw_machine_8_0_instance_options(MachineState *machine) { + ccw_machine_8_1_instance_options(machine); } static void ccw_machine_8_0_class_options(MachineClass *mc) { + ccw_machine_8_1_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len); } -DEFINE_CCW_MACHINE(8_0, "8.0", true); +DEFINE_CCW_MACHINE(8_0, "8.0", false); static void ccw_machine_7_2_instance_options(MachineState *machine) { diff --git a/include/hw/boards.h b/include/hw/boards.h index 6fbbfd56c8..bf5fc9e3e7 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -381,6 +381,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_8_0[]; +extern const size_t hw_compat_8_0_len; + extern GlobalProperty hw_compat_7_2[]; extern const size_t hw_compat_7_2_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 8206d5405a..eb668e9034 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -195,6 +195,9 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList *apic_ids, /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); +extern GlobalProperty pc_compat_8_0[]; +extern const size_t pc_compat_8_0_len; + extern GlobalProperty pc_compat_7_2[]; extern const size_t pc_compat_7_2_len; From ca45a640b36e2bc7e3129293f3fcae5abc4c26f8 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 9 Apr 2023 22:10:07 +0200 Subject: [PATCH 02/23] docs: Fix typo (wphx => whpx) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1529 Signed-off-by: Stefan Weil Message-Id: <20230409201007.1157671-1-sw@weilnetz.de> Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- docs/system/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/system/introduction.rst b/docs/system/introduction.rst index c8a9fe6c1d..3e256f8326 100644 --- a/docs/system/introduction.rst +++ b/docs/system/introduction.rst @@ -27,7 +27,7 @@ Tiny Code Generator (TCG) capable of emulating many CPUs. * - Hypervisor Framework (hvf) - MacOS - x86 (64 bit only), Arm (64 bit only) - * - Windows Hypervisor Platform (wphx) + * - Windows Hypervisor Platform (whpx) - Windows - x86 * - NetBSD Virtual Machine Monitor (nvmm) From 63cec0506e32467ec94db2973a9459147f081abf Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 9 Apr 2023 22:18:28 +0200 Subject: [PATCH 03/23] docs/cxl: Fix sentence Signed-off-by: Stefan Weil Message-Id: <20230409201828.1159568-1-sw@weilnetz.de> Reviewed-by: Richard Henderson Acked-by: Jonathan Cameron Signed-off-by: Thomas Huth --- docs/system/devices/cxl.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst index f25783a4ec..4c38223069 100644 --- a/docs/system/devices/cxl.rst +++ b/docs/system/devices/cxl.rst @@ -111,7 +111,7 @@ Interfaces provided include: CXL Root Ports (CXL RP) ~~~~~~~~~~~~~~~~~~~~~~~ -A CXL Root Port servers te same purpose as a PCIe Root Port. +A CXL Root Port serves the same purpose as a PCIe Root Port. There are a number of CXL specific Designated Vendor Specific Extended Capabilities (DVSEC) in PCIe Configuration Space and associated component register access via PCI bars. From 9a29e02073e5d032e49fb3af992b6065bd2acd3c Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 14 Apr 2023 13:42:52 +0200 Subject: [PATCH 04/23] test: Fix test-crypto-secret when compiling without keyring support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux keyring support is protected by CONFIG_KEYUTILS. We also need CONFIG_SECRET_KEYRING. Signed-off-by: Juan Quintela Message-Id: <20230414114252.1136-1-quintela@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- tests/unit/test-crypto-secret.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit/test-crypto-secret.c b/tests/unit/test-crypto-secret.c index 34a4aecc12..147b4af828 100644 --- a/tests/unit/test-crypto-secret.c +++ b/tests/unit/test-crypto-secret.c @@ -24,7 +24,7 @@ #include "crypto/secret.h" #include "qapi/error.h" #include "qemu/module.h" -#ifdef CONFIG_KEYUTILS +#if defined(CONFIG_KEYUTILS) && defined(CONFIG_SECRET_KEYRING) #include "crypto/secret_keyring.h" #include #endif @@ -128,7 +128,7 @@ static void test_secret_indirect_emptyfile(void) g_free(fname); } -#ifdef CONFIG_KEYUTILS +#if defined(CONFIG_KEYUTILS) && defined(CONFIG_SECRET_KEYRING) #define DESCRIPTION "qemu_test_secret" #define PAYLOAD "Test Payload" @@ -268,7 +268,7 @@ static void test_secret_keyring_bad_key_access_right(void) keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING); } -#endif /* CONFIG_KEYUTILS */ +#endif /* CONFIG_KEYUTILS && CONFIG_SECRET_KEYRING */ static void test_secret_noconv_base64_good(void) { @@ -571,7 +571,7 @@ int main(int argc, char **argv) g_test_add_func("/crypto/secret/indirect/emptyfile", test_secret_indirect_emptyfile); -#ifdef CONFIG_KEYUTILS +#if defined(CONFIG_KEYUTILS) && defined(CONFIG_SECRET_KEYRING) g_test_add_func("/crypto/secret/keyring/good", test_secret_keyring_good); g_test_add_func("/crypto/secret/keyring/revoked_key", @@ -582,7 +582,7 @@ int main(int argc, char **argv) test_secret_keyring_bad_serial_key); g_test_add_func("/crypto/secret/keyring/bad_key_access_right", test_secret_keyring_bad_key_access_right); -#endif /* CONFIG_KEYUTILS */ +#endif /* CONFIG_KEYUTILS && CONFIG_SECRET_KEYRING */ g_test_add_func("/crypto/secret/noconv/base64/good", test_secret_noconv_base64_good); From 537a1388e65a784ac21eaf1639222e6332357b2f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 13 Apr 2023 16:07:23 +0100 Subject: [PATCH 05/23] qtest: Don't assert on "-qtest chardev:myid" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the -qtest command line argument is passed a string that says "use this chardev for I/O", then it will assert: $ ./build/clang/qemu-system-i386 -chardev file,path=/dev/null,id=myid -qtest chardev:myid Unexpected error in qtest_set_chardev() at ../../softmmu/qtest.c:1011: qemu-system-i386: Cannot find character device 'qtest' Aborted (core dumped) This is because in qtest_server_init() we assume that when we create the chardev with qemu_chr_new() it will always have the name "qtest". This is true if qemu_chr_new() had to create a new chardev, but not true if one already existed and is being referred to with "chardev:myid". Use the name of the chardev we get back from qemu_chr_new() as the string to set the qtest 'chardev' property to, instead of hardcoding it to "qtest". Signed-off-by: Peter Maydell Message-Id: <20230413150724.404304-2-peter.maydell@linaro.org> Reviewed-by: Marc-André Lureau Reviewed-by: Thomas Huth Signed-off-by: Thomas Huth --- softmmu/qtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/softmmu/qtest.c b/softmmu/qtest.c index 34bd2a33a7..26852996b5 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -867,7 +867,7 @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error ** } qtest = object_new(TYPE_QTEST); - object_property_set_str(qtest, "chardev", "qtest", &error_abort); + object_property_set_str(qtest, "chardev", chr->label, &error_abort); if (qtest_log) { object_property_set_str(qtest, "log", qtest_log, &error_abort); } From 5b18a6bf44b93122ba6638d227153cd146a68973 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 13 Apr 2023 16:07:24 +0100 Subject: [PATCH 06/23] chardev: Allow setting file chardev input file on the command line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our 'file' chardev backend supports both "output from this chardev is written to a file" and "input from this chardev should be read from a file" (except on Windows). However, you can only set up the input file if you're using the QMP interface -- there is no command line syntax to do it. Add command line syntax to allow specifying an input file as well as an output file, using a new 'input-path' suboption. The specific use case I have is that I'd like to be able to feed fuzzer reproducer input into qtest without having to use '-qtest stdio' and put the input onto stdin. Being able to use a file chardev like this: -chardev file,id=repro,path=/dev/null,input-path=repro.txt -qtest chardev:repro means that stdio is free for use by gdb. Signed-off-by: Peter Maydell Message-Id: <20230413150724.404304-3-peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau [thuth: Replace "input-file=" typo with "input-path="] Signed-off-by: Thomas Huth --- chardev/char-file.c | 8 ++++++++ chardev/char.c | 3 +++ qemu-options.hx | 10 ++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/chardev/char-file.c b/chardev/char-file.c index 3a7b9caf6f..263e6da563 100644 --- a/chardev/char-file.c +++ b/chardev/char-file.c @@ -100,6 +100,7 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend, Error **errp) { const char *path = qemu_opt_get(opts, "path"); + const char *inpath = qemu_opt_get(opts, "input-path"); ChardevFile *file; backend->type = CHARDEV_BACKEND_KIND_FILE; @@ -107,9 +108,16 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: file: no filename given"); return; } +#ifdef _WIN32 + if (inpath) { + error_setg(errp, "chardev: file: input-path not supported on Windows"); + return; + } +#endif file = backend->u.file.data = g_new0(ChardevFile, 1); qemu_chr_parse_common(opts, qapi_ChardevFile_base(file)); file->out = g_strdup(path); + file->in = g_strdup(inpath); file->has_append = true; file->append = qemu_opt_get_bool(opts, "append", false); diff --git a/chardev/char.c b/chardev/char.c index e69390601f..661ad8176a 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -805,6 +805,9 @@ QemuOptsList qemu_chardev_opts = { },{ .name = "path", .type = QEMU_OPT_STRING, + },{ + .name = "input-path", + .type = QEMU_OPT_STRING, },{ .name = "host", .type = QEMU_OPT_STRING, diff --git a/qemu-options.hx b/qemu-options.hx index 59bdf67a2c..04c259157a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3360,7 +3360,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n" " [,mux=on|off][,logfile=PATH][,logappend=on|off]\n" "-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n" - "-chardev file,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n" "-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" #ifdef _WIN32 "-chardev console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" @@ -3563,13 +3563,19 @@ The available backends are: Create a ring buffer with fixed size ``size``. size must be a power of two and defaults to ``64K``. -``-chardev file,id=id,path=path`` +``-chardev file,id=id,path=path[,input-path=input-path]`` Log all traffic received from the guest to a file. ``path`` specifies the path of the file to be opened. This file will be created if it does not already exist, and overwritten if it does. ``path`` is required. + If ``input-path`` is specified, this is the path of a second file + which will be used for input. If ``input-path`` is not specified, + no input will be available from the chardev. + + Note that ``input-path`` is not supported on Windows hosts. + ``-chardev pipe,id=id,path=path`` Create a two-way connection to the guest. The behaviour differs slightly between Windows hosts and other hosts: From a53be6665905a2eb9c56f3e3d8a167a2d2113d31 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Sat, 15 Apr 2023 02:36:44 +0530 Subject: [PATCH 07/23] travis.yml: Add missing clang-10 package to the 'Clang (disable-tcg)' job Since commit 74a1b256d775("configure: Bump minimum Clang version to 10.0") qemu needs Clang version 10.0 as the minimum version to build qemu with Clang. However 'focal' ships by default with Clang version 7.0.0 which causes an error while executing the 'Clang (disable-tcg)' travis job of the form below: $clang --version clang version 7.0.0 (tags/RELEASE_700/final) ERROR: You need at least GCC v7.4 or Clang v10.0 (or XCode Clang v12.0) # QEMU configure log Fri 14 Apr 2023 03:48:22 PM UTC # Configured with: '../configure' '--disable-docs' '--disable-tools' '--disable-containers' '--disable-tcg' '--enable-kvm' '--disable-tools' '--enable-fdt=system' '--host-cc=clang' '--cxx=clang++' Fix this by adding 'clang-10' to the 'apt_packages' section of the "[s390x] Clang (disable-tcg)" job and updating the compiler to 'clang-10'. Signed-off-by: Vaibhav Jain Message-Id: <20230414210645.820204-1-vaibhav@linux.ibm.com> Signed-off-by: Thomas Huth --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cf088ba4cf..11894eb810 100644 --- a/.travis.yml +++ b/.travis.yml @@ -243,7 +243,7 @@ jobs: - name: "[s390x] Clang (disable-tcg)" arch: s390x dist: focal - compiler: clang + compiler: clang-10 addons: apt_packages: - libaio-dev @@ -269,6 +269,7 @@ jobs: - libvdeplug-dev - libvte-2.91-dev - ninja-build + - clang-10 env: - TEST_CMD="make check-unit" - CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools From e23130f916b07d5a41dba9e06327d1e76713e85f Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Mon, 17 Apr 2023 21:53:54 +0530 Subject: [PATCH 08/23] travis.yml: Add missing 'flex', 'bison' packages to 'GCC (user)' job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit fd8171fe52b5e("target/hexagon: import lexer for idef-parser") the hexagon target uses 'flex', 'bison' to generate idef-parser. However default travis builder image for 'focal' may not have these pre-installed, consequently following error is seen with travis when trying to execute the 'GCC (user)' job that also tries to build hexagon user binary: export CONFIG="--disable-containers --disable-system" Program flex found: NO ../target/hexagon/meson.build:179:4: ERROR: Program 'flex' not found or not executable Fix this by explicitly add 'flex' and 'bison' to the list of addon apt-packages for the 'GCC (user)' job. Signed-off-by: Vaibhav Jain Message-Id: <20230417162354.186678-1-vaibhav@linux.ibm.com> Reviewed-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 11894eb810..b958eca5de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -237,6 +237,8 @@ jobs: - libglib2.0-dev - libgnutls28-dev - ninja-build + - flex + - bison env: - CONFIG="--disable-containers --disable-system" From 74902af7379cdcadca2ccbfe443bc211fb7a01fd Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 12 Apr 2023 16:20:01 +0200 Subject: [PATCH 09/23] tests/migration: Only run auto_converge in slow mode Signed-off-by: Juan Quintela Message-Id: <20230412142001.16501-3-quintela@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 3b615b0da9..60dd53d3ec 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1796,6 +1796,21 @@ static void test_validate_uuid_dst_not_set(void) do_test_validate_uuid(&args, false); } +/* + * The way auto_converge works, we need to do too many passes to + * run this test. Auto_converge logic is only run once every + * three iterations, so: + * + * - 3 iterations without auto_converge enabled + * - 3 iterations with pct = 5 + * - 3 iterations with pct = 30 + * - 3 iterations with pct = 55 + * - 3 iterations with pct = 80 + * - 3 iterations with pct = 95 (max(95, 80 + 25)) + * + * To make things even worse, we need to run the initial stage at + * 3MB/s so we enter autoconverge even when host is (over)loaded. + */ static void test_migrate_auto_converge(void) { g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); @@ -2575,8 +2590,12 @@ int main(int argc, char **argv) test_validate_uuid_src_not_set); qtest_add_func("/migration/validate_uuid_dst_not_set", test_validate_uuid_dst_not_set); - - qtest_add_func("/migration/auto_converge", test_migrate_auto_converge); + /* + * See explanation why this test is slow on function definition + */ + if (g_test_slow()) { + qtest_add_func("/migration/auto_converge", test_migrate_auto_converge); + } qtest_add_func("/migration/multifd/tcp/plain/none", test_multifd_tcp_none); /* From 123fa10279572dff2a280a8170e0888e0bf0bf79 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 6 Mar 2023 16:43:11 +0100 Subject: [PATCH 10/23] target/i386: Set family/model/stepping of the "max" CPU according to LM bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to get rid of the "#ifdef TARGET_X86_64" compile-time switch in the long run, so we can drop the separate compilation of the "qemu-system-i386" binary one day - but we then still need a way to run a guest with max. CPU settings in 32-bit mode. So the "max" CPU should determine its family/model/stepping settings according to the "large mode" (LM) CPU feature bit during runtime, so that it is possible to run "qemu-system-x86_64 -cpu max,lm=off" and still get a sane family/model/stepping setting for the guest CPU. To be able to check the LM bit, we have to move the code that sets up these properties to a "realize" function, since the LM setting is not available yet when the "instance_init" function is being called. Message-Id: <20230306154311.476458-1-thuth@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- target/i386/cpu.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6576287e5b..95c0dcd493 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -45,6 +45,8 @@ #include "disas/capstone.h" #include "cpu-internal.h" +static void x86_cpu_realizefn(DeviceState *dev, Error **errp); + /* Helpers for building CPUID[2] descriptors: */ struct CPUID2CacheDescriptorInfo { @@ -4316,6 +4318,25 @@ static Property max_x86_cpu_properties[] = { DEFINE_PROP_END_OF_LIST() }; +static void max_x86_cpu_realize(DeviceState *dev, Error **errp) +{ + Object *obj = OBJECT(dev); + + if (!object_property_get_int(obj, "family", &error_abort)) { + if (X86_CPU(obj)->env.features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { + object_property_set_int(obj, "family", 15, &error_abort); + object_property_set_int(obj, "model", 107, &error_abort); + object_property_set_int(obj, "stepping", 1, &error_abort); + } else { + object_property_set_int(obj, "family", 6, &error_abort); + object_property_set_int(obj, "model", 6, &error_abort); + object_property_set_int(obj, "stepping", 3, &error_abort); + } + } + + x86_cpu_realizefn(dev, errp); +} + static void max_x86_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -4327,6 +4348,7 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data) "Enables all features supported by the accelerator in the current host"; device_class_set_props(dc, max_x86_cpu_properties); + dc->realize = max_x86_cpu_realize; } static void max_x86_cpu_initfn(Object *obj) @@ -4345,15 +4367,6 @@ static void max_x86_cpu_initfn(Object *obj) */ object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD, &error_abort); -#ifdef TARGET_X86_64 - object_property_set_int(OBJECT(cpu), "family", 15, &error_abort); - object_property_set_int(OBJECT(cpu), "model", 107, &error_abort); - object_property_set_int(OBJECT(cpu), "stepping", 1, &error_abort); -#else - object_property_set_int(OBJECT(cpu), "family", 6, &error_abort); - object_property_set_int(OBJECT(cpu), "model", 6, &error_abort); - object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort); -#endif object_property_set_str(OBJECT(cpu), "model-id", "QEMU TCG CPU version " QEMU_HW_VERSION, &error_abort); From 8708c46306b8422eb0cbb882f88cdad29c041725 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 11 Apr 2023 19:32:06 +0200 Subject: [PATCH 11/23] hw/char: Move two more files from specific_ss to softmmu_ss The code for these two devices seems to be independent from any target specific macros. "riscv_htif.c" is used for both, riscv32 and riscv64, so by moving this to the common code source set, we can avoid to compile it twice every time. "goldfish_tty.c" is only used for one target at the moment, but since it is a paravirtualized device, it could get useful for other targets one day, so let's move it now, too. Message-Id: <20230411173206.1511621-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- hw/char/meson.build | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/char/meson.build b/hw/char/meson.build index e02c60dd54..0807e00ae4 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -32,10 +32,9 @@ softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c')) softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c')) softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c')) softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c')) +softmmu_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c')) +softmmu_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c')) -specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c')) specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c')) specific_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-serial-bus.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_vty.c')) - -specific_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c')) From c7a6bf5d921a25bf1d59143e63b453affe6c8892 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 11 Apr 2023 20:34:16 +0200 Subject: [PATCH 12/23] softmmu/qtest: Move the target-specific pseries RTAS code out of qtest.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ideally, qtest.c should be independent from target specific code, so we only have to compile it once for all targets. Thus start improving the situation by moving the pseries related code to hw/ppc/spapr_rtas.c instead and allow target code to register a callback handler for such target specific commands. Message-Id: <20230411183418.1640500-2-thuth@redhat.com> Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Thomas Huth --- hw/ppc/spapr_rtas.c | 29 +++++++++++++++++++++++++++++ include/sysemu/qtest.h | 4 ++++ softmmu/qtest.c | 39 +++++++++++++-------------------------- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 3f664ea02c..7df21581c2 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -33,6 +33,7 @@ #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" #include "sysemu/runstate.h" +#include "sysemu/qtest.h" #include "kvm_ppc.h" #include "hw/ppc/spapr.h" @@ -548,6 +549,32 @@ uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args, return H_PARAMETER; } +static bool spapr_qtest_callback(CharBackend *chr, gchar **words) +{ + if (strcmp(words[0], "rtas") == 0) { + uint64_t res, args, ret; + unsigned long nargs, nret; + int rc; + + rc = qemu_strtoul(words[2], NULL, 0, &nargs); + g_assert(rc == 0); + rc = qemu_strtou64(words[3], NULL, 0, &args); + g_assert(rc == 0); + rc = qemu_strtoul(words[4], NULL, 0, &nret); + g_assert(rc == 0); + rc = qemu_strtou64(words[5], NULL, 0, &ret); + g_assert(rc == 0); + res = qtest_rtas_call(words[1], nargs, args, nret, ret); + + qtest_send_prefix(chr); + qtest_sendf(chr, "OK %"PRIu64"\n", res); + + return true; + } + + return false; +} + void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn) { assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)); @@ -630,6 +657,8 @@ static void core_rtas_register_types(void) rtas_ibm_nmi_register); spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock", rtas_ibm_nmi_interlock); + + qtest_set_command_cb(spapr_qtest_callback); } type_init(core_rtas_register_types) diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h index 4c53537ef3..85f05b0e46 100644 --- a/include/sysemu/qtest.h +++ b/include/sysemu/qtest.h @@ -14,6 +14,7 @@ #ifndef QTEST_H #define QTEST_H +#include "chardev/char.h" extern bool qtest_allowed; @@ -22,6 +23,9 @@ static inline bool qtest_enabled(void) return qtest_allowed; } +void qtest_send_prefix(CharBackend *chr); +void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr, const char *fmt, ...); +void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words)); bool qtest_driver(void); void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp); diff --git a/softmmu/qtest.c b/softmmu/qtest.c index 26852996b5..09126df38a 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -29,10 +29,6 @@ #include "qemu/module.h" #include "qemu/cutils.h" #include "qom/object_interfaces.h" -#include CONFIG_DEVICES -#ifdef CONFIG_PSERIES -#include "hw/ppc/spapr_rtas.h" -#endif #define MAX_IRQ 256 @@ -263,7 +259,7 @@ static int hex2nib(char ch) } } -static void qtest_send_prefix(CharBackend *chr) +void qtest_send_prefix(CharBackend *chr) { if (!qtest_log_fp || !qtest_opened) { return; @@ -302,8 +298,7 @@ static void qtest_send(CharBackend *chr, const char *str) qtest_server_send(qtest_server_send_opaque, str); } -static void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr, - const char *fmt, ...) +void qtest_sendf(CharBackend *chr, const char *fmt, ...) { va_list ap; gchar *buffer; @@ -361,6 +356,15 @@ static void qtest_clock_warp(int64_t dest) qemu_clock_notify(QEMU_CLOCK_VIRTUAL); } +static bool (*process_command_cb)(CharBackend *chr, gchar **words); + +void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words)) +{ + assert(!process_command_cb); /* Switch to a list if we need more than one */ + + process_command_cb = pc_cb; +} + static void qtest_process_command(CharBackend *chr, gchar **words) { const gchar *command; @@ -717,25 +721,6 @@ static void qtest_process_command(CharBackend *chr, gchar **words) qtest_sendf(chr, "OK big\n"); #else qtest_sendf(chr, "OK little\n"); -#endif -#ifdef CONFIG_PSERIES - } else if (strcmp(words[0], "rtas") == 0) { - uint64_t res, args, ret; - unsigned long nargs, nret; - int rc; - - rc = qemu_strtoul(words[2], NULL, 0, &nargs); - g_assert(rc == 0); - rc = qemu_strtou64(words[3], NULL, 0, &args); - g_assert(rc == 0); - rc = qemu_strtoul(words[4], NULL, 0, &nret); - g_assert(rc == 0); - rc = qemu_strtou64(words[5], NULL, 0, &ret); - g_assert(rc == 0); - res = qtest_rtas_call(words[1], nargs, args, nret, ret); - - qtest_send_prefix(chr); - qtest_sendf(chr, "OK %"PRIu64"\n", res); #endif } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) { int64_t ns; @@ -777,6 +762,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words) qtest_send_prefix(chr); qtest_sendf(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); + } else if (process_command_cb && process_command_cb(chr, words)) { + /* Command got consumed by the callback handler */ } else { qtest_send_prefix(chr); qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]); From 24be3369ad63c3882be42dd510a45bad52816fd1 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 11 Apr 2023 20:34:17 +0200 Subject: [PATCH 13/23] include/exec: Provide the tswap() functions for target independent code, too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases of target independent code, it would be useful to have access to the functions that swap endianess in case it differs between guest and host. Thus re-implement the tswapXX() functions in a new header that can be included separately. The check whether the swapping is needed continues to be done at compile-time for target specific code, while it is done at run-time in target-independent code. Message-Id: <20230411183418.1640500-3-thuth@redhat.com> Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Thomas Huth --- include/exec/cpu-all.h | 64 +------------------------------------ include/exec/tswap.h | 72 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 63 deletions(-) create mode 100644 include/exec/tswap.h diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 090922e4a8..ad824fee52 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -21,6 +21,7 @@ #include "exec/cpu-common.h" #include "exec/memory.h" +#include "exec/tswap.h" #include "qemu/thread.h" #include "hw/core/cpu.h" #include "qemu/rcu.h" @@ -44,69 +45,6 @@ #define BSWAP_NEEDED #endif -#ifdef BSWAP_NEEDED - -static inline uint16_t tswap16(uint16_t s) -{ - return bswap16(s); -} - -static inline uint32_t tswap32(uint32_t s) -{ - return bswap32(s); -} - -static inline uint64_t tswap64(uint64_t s) -{ - return bswap64(s); -} - -static inline void tswap16s(uint16_t *s) -{ - *s = bswap16(*s); -} - -static inline void tswap32s(uint32_t *s) -{ - *s = bswap32(*s); -} - -static inline void tswap64s(uint64_t *s) -{ - *s = bswap64(*s); -} - -#else - -static inline uint16_t tswap16(uint16_t s) -{ - return s; -} - -static inline uint32_t tswap32(uint32_t s) -{ - return s; -} - -static inline uint64_t tswap64(uint64_t s) -{ - return s; -} - -static inline void tswap16s(uint16_t *s) -{ -} - -static inline void tswap32s(uint32_t *s) -{ -} - -static inline void tswap64s(uint64_t *s) -{ -} - -#endif - #if TARGET_LONG_SIZE == 4 #define tswapl(s) tswap32(s) #define tswapls(s) tswap32s((uint32_t *)(s)) diff --git a/include/exec/tswap.h b/include/exec/tswap.h new file mode 100644 index 0000000000..68944a880b --- /dev/null +++ b/include/exec/tswap.h @@ -0,0 +1,72 @@ +/* + * Macros for swapping a value if the endianness is different + * between the target and the host. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef TSWAP_H +#define TSWAP_H + +#include "hw/core/cpu.h" +#include "qemu/bswap.h" + +/* + * If we're in target-specific code, we can hard-code the swapping + * condition, otherwise we have to do (slower) run-time checks. + */ +#ifdef NEED_CPU_H +#define target_needs_bswap() (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN) +#else +#define target_needs_bswap() (target_words_bigendian() != HOST_BIG_ENDIAN) +#endif + +static inline uint16_t tswap16(uint16_t s) +{ + if (target_needs_bswap()) { + return bswap16(s); + } else { + return s; + } +} + +static inline uint32_t tswap32(uint32_t s) +{ + if (target_needs_bswap()) { + return bswap32(s); + } else { + return s; + } +} + +static inline uint64_t tswap64(uint64_t s) +{ + if (target_needs_bswap()) { + return bswap64(s); + } else { + return s; + } +} + +static inline void tswap16s(uint16_t *s) +{ + if (target_needs_bswap()) { + *s = bswap16(*s); + } +} + +static inline void tswap32s(uint32_t *s) +{ + if (target_needs_bswap()) { + *s = bswap32(*s); + } +} + +static inline void tswap64s(uint64_t *s) +{ + if (target_needs_bswap()) { + *s = bswap64(*s); + } +} + +#endif /* TSWAP_H */ From 09637edb84556e08dac10a13e7801918e4666d93 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 11 Apr 2023 20:34:18 +0200 Subject: [PATCH 14/23] softmmu: Make qtest.c target independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code in this file is not performance critical, so we can use the target independent endianess functions to only compile this file once for all targets. Message-Id: <20230411183418.1640500-4-thuth@redhat.com> Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Thomas Huth --- softmmu/meson.build | 2 +- softmmu/qtest.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/softmmu/meson.build b/softmmu/meson.build index 1a7c7ac089..b392f0bd35 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -3,7 +3,6 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'ioport.c', 'memory.c', 'physmem.c', - 'qtest.c', 'dirtylimit.c', 'watchpoint.c', )]) @@ -23,6 +22,7 @@ softmmu_ss.add(files( 'globals.c', 'memory_mapping.c', 'qdev-monitor.c', + 'qtest.c', 'rtc.c', 'runstate-action.c', 'runstate-hmp-cmds.c', diff --git a/softmmu/qtest.c b/softmmu/qtest.c index 09126df38a..f8d764b719 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -13,12 +13,12 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "cpu.h" #include "sysemu/qtest.h" #include "sysemu/runstate.h" #include "chardev/char-fe.h" #include "exec/ioport.h" #include "exec/memory.h" +#include "exec/tswap.h" #include "hw/qdev-core.h" #include "hw/irq.h" #include "qemu/accel.h" @@ -717,11 +717,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words) qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "endianness") == 0) { qtest_send_prefix(chr); -#if TARGET_BIG_ENDIAN - qtest_sendf(chr, "OK big\n"); -#else - qtest_sendf(chr, "OK little\n"); -#endif + if (target_words_bigendian()) { + qtest_sendf(chr, "OK big\n"); + } else { + qtest_sendf(chr, "OK little\n"); + } } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) { int64_t ns; From 9eb7e7e84af5362b125015e80fdaab96b944f6f2 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Apr 2023 18:35:01 +0200 Subject: [PATCH 15/23] hw/display: Compile vga.c as target-independent code The target checks here are only during the initialization, so they are not performance critical. We can switch these to runtime checks to avoid that we have to compile this file multiple times during the build, and make the code ready for an universal build one day. Message-Id: <20230412163501.36770-1-thuth@redhat.com> Reviewed-by: Fabiano Rosas Signed-off-by: Thomas Huth --- hw/display/meson.build | 2 +- hw/display/vga.c | 31 ++++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/hw/display/meson.build b/hw/display/meson.build index 4191694380..17165bd536 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -36,7 +36,7 @@ softmmu_ss.add(when: 'CONFIG_CG3', if_true: files('cg3.c')) softmmu_ss.add(when: 'CONFIG_MACFB', if_true: files('macfb.c')) softmmu_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c')) -specific_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c')) +softmmu_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c')) if (config_all_devices.has_key('CONFIG_VGA_CIRRUS') or config_all_devices.has_key('CONFIG_VGA_PCI') or diff --git a/hw/display/vga.c b/hw/display/vga.c index 7a5fdff649..37557c3442 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -26,7 +26,9 @@ #include "qemu/units.h" #include "sysemu/reset.h" #include "qapi/error.h" +#include "hw/core/cpu.h" #include "hw/display/vga.h" +#include "hw/i386/x86.h" #include "hw/pci/pci.h" #include "vga_int.h" #include "vga_regs.h" @@ -2244,11 +2246,8 @@ bool vga_common_init(VGACommonState *s, Object *obj, Error **errp) * into a device attribute set by the machine/platform to remove * all target endian dependencies from this file. */ -#if TARGET_BIG_ENDIAN - s->default_endian_fb = true; -#else - s->default_endian_fb = false; -#endif + s->default_endian_fb = target_words_bigendian(); + vga_dirty_log_start(s); return true; @@ -2263,11 +2262,15 @@ static const MemoryRegionPortio vga_portio_list[] = { PORTIO_END_OF_LIST(), }; -static const MemoryRegionPortio vbe_portio_list[] = { +static const MemoryRegionPortio vbe_portio_list_x86[] = { { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index }, -# ifdef TARGET_I386 { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, -# endif + { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionPortio vbe_portio_list_no_x86[] = { + { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index }, { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, PORTIO_END_OF_LIST(), }; @@ -2278,9 +2281,19 @@ MemoryRegion *vga_init_io(VGACommonState *s, Object *obj, const MemoryRegionPortio **vbe_ports) { MemoryRegion *vga_mem; + MachineState *ms = MACHINE(qdev_get_machine()); + + /* + * We unfortunately need two VBE lists since non-x86 machines might + * not be able to do 16-bit accesses at unaligned addresses (0x1cf) + */ + if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) { + *vbe_ports = vbe_portio_list_x86; + } else { + *vbe_ports = vbe_portio_list_no_x86; + } *vga_ports = vga_portio_list; - *vbe_ports = vbe_portio_list; vga_mem = g_malloc(sizeof(*vga_mem)); memory_region_init_io(vga_mem, obj, &vga_mem_ops, s, From 30ee29fd03bbdd4cc250c1a591c5199b33e7a118 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 13 Apr 2023 07:45:09 +0200 Subject: [PATCH 16/23] softmmu: Move dirtylimit.c into the target independent source set dirtylimit.c just uses one TARGET_PAGE_SIZE macro - change it to qemu_target_page_size() so we can move thefile into the target independent source set. Then we only have to compile this file once during the build instead of multiple times (one time for each target). Message-Id: <20230413054509.54421-1-thuth@redhat.com> Reviewed-by: Fabiano Rosas Signed-off-by: Thomas Huth --- softmmu/dirtylimit.c | 3 ++- softmmu/meson.build | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c index c56f0f58c8..82986c1499 100644 --- a/softmmu/dirtylimit.c +++ b/softmmu/dirtylimit.c @@ -20,6 +20,7 @@ #include "monitor/hmp.h" #include "monitor/monitor.h" #include "exec/memory.h" +#include "exec/target_page.h" #include "hw/boards.h" #include "sysemu/kvm.h" #include "trace.h" @@ -236,7 +237,7 @@ static inline int64_t dirtylimit_dirty_ring_full_time(uint64_t dirtyrate) static uint64_t max_dirtyrate; uint32_t dirty_ring_size = kvm_dirty_ring_size(); uint64_t dirty_ring_size_meory_MB = - dirty_ring_size * TARGET_PAGE_SIZE >> 20; + dirty_ring_size * qemu_target_page_size() >> 20; if (max_dirtyrate < dirtyrate) { max_dirtyrate = dirtyrate; diff --git a/softmmu/meson.build b/softmmu/meson.build index b392f0bd35..974732b0f3 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -3,7 +3,6 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'ioport.c', 'memory.c', 'physmem.c', - 'dirtylimit.c', 'watchpoint.c', )]) @@ -18,6 +17,7 @@ softmmu_ss.add(files( 'cpu-throttle.c', 'cpu-timers.c', 'datadir.c', + 'dirtylimit.c', 'dma-helpers.c', 'globals.c', 'memory_mapping.c', From 992deb4c4ff88540edf4f337238e5f84dcdab094 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 13 Apr 2023 20:26:36 +0200 Subject: [PATCH 17/23] hw/core: Move numa.c into the target independent source set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is nothing that depends on target specific macros in this file, so we can move it to the common source set to avoid that we have to compile this file multiple times (one time for each target). Message-Id: <20230413182636.139356-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- hw/core/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/core/meson.build b/hw/core/meson.build index 7a4d02b6c0..ae977c9396 100644 --- a/hw/core/meson.build +++ b/hw/core/meson.build @@ -44,6 +44,7 @@ softmmu_ss.add(files( 'machine.c', 'nmi.c', 'null-machine.c', + 'numa.c', 'qdev-fw.c', 'qdev-properties-system.c', 'sysbus.c', @@ -53,5 +54,4 @@ softmmu_ss.add(files( specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files( 'machine-qmp-cmds.c', - 'numa.c', )) From c138c3b864245d7721a03f01f97e70e47d253839 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 19 Apr 2023 14:48:31 +0200 Subject: [PATCH 18/23] cpu: Remove parameter of list_cpus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "optarg" parameter is completely unused, so let's drop it. Message-Id: <20230419124831.678079-1-thuth@redhat.com> Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- cpu.c | 2 +- include/exec/cpu-common.h | 2 +- softmmu/vl.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpu.c b/cpu.c index 849bac062c..9105c85404 100644 --- a/cpu.c +++ b/cpu.c @@ -284,7 +284,7 @@ const char *parse_cpu_option(const char *cpu_option) return cpu_type; } -void list_cpus(const char *optarg) +void list_cpus(void) { /* XXX: implement xxx_cpu_list for targets that still miss it */ #if defined(cpu_list) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 6feaa40ca7..565c2030c1 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -165,6 +165,6 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, /* vl.c */ extern int singlestep; -void list_cpus(const char *optarg); +void list_cpus(void); #endif /* CPU_COMMON_H */ diff --git a/softmmu/vl.c b/softmmu/vl.c index ea20b23e4c..5cb72a56fc 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2432,7 +2432,7 @@ static void qemu_process_help_options(void) * to say '-cpu help -machine something'. */ if (cpu_option && is_help_option(cpu_option)) { - list_cpus(cpu_option); + list_cpus(); exit(0); } From 2243299a748dbc7581205e043dcdb66627a062dd Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 19 Apr 2023 18:34:57 +0200 Subject: [PATCH 19/23] MAINTAINERS: Add Juan Quintela to developer guides review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Juan Quintela Message-Id: <20230419163457.17175-1-quintela@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2c2068ea5c..24154f5721 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -70,6 +70,7 @@ R: Daniel P. Berrangé R: Thomas Huth R: Markus Armbruster R: Philippe Mathieu-Daudé +R: Juan Quintela W: https://www.qemu.org/docs/master/devel/index.html S: Odd Fixes F: docs/devel/style.rst From a3ebb580a21c89d22ac5f52bd70814c997f28893 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 31 Mar 2023 13:30:49 -0400 Subject: [PATCH 20/23] qtest: Add functions for accessing devices on Aspeed I2C controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add read and write functions for accessing registers of I2C devices connected to the Aspeed I2C controller. Signed-off-by: Stefan Berger Reviewed-by: Cédric Le Goater Reviewed-by: Ninad Palsule Message-Id: <20230331173051.3857801-2-stefanb@linux.ibm.com> Signed-off-by: Thomas Huth --- include/hw/i2c/aspeed_i2c.h | 7 +++ tests/qtest/qtest_aspeed.c | 117 ++++++++++++++++++++++++++++++++++++ tests/qtest/qtest_aspeed.h | 41 +++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 tests/qtest/qtest_aspeed.c create mode 100644 tests/qtest/qtest_aspeed.h diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index adc904d6c1..51c944efea 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -38,6 +38,13 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) #define ASPEED_I2C_OLD_NUM_REG 11 #define ASPEED_I2C_NEW_NUM_REG 22 +#define A_I2CD_M_STOP_CMD BIT(5) +#define A_I2CD_M_RX_CMD BIT(3) +#define A_I2CD_M_TX_CMD BIT(1) +#define A_I2CD_M_START_CMD BIT(0) + +#define A_I2CD_MASTER_EN BIT(0) + /* Tx State Machine */ #define I2CD_TX_STATE_MASK 0xf #define I2CD_IDLE 0x0 diff --git a/tests/qtest/qtest_aspeed.c b/tests/qtest/qtest_aspeed.c new file mode 100644 index 0000000000..f6da9adea9 --- /dev/null +++ b/tests/qtest/qtest_aspeed.c @@ -0,0 +1,117 @@ +/* + * Aspeed i2c bus interface for reading from and writing to i2c device registers + * + * Copyright (c) 2023 IBM Corporation + * + * Authors: + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +#include "qtest_aspeed.h" +#include "hw/i2c/aspeed_i2c.h" + +static void aspeed_i2c_startup(QTestState *s, uint32_t baseaddr, + uint8_t slave_addr, uint8_t reg) +{ + uint32_t v; + static int once; + + if (!once) { + /* one time: enable master */ + qtest_writel(s, baseaddr + A_I2CC_FUN_CTRL, 0); + v = qtest_readl(s, baseaddr + A_I2CC_FUN_CTRL) | A_I2CD_MASTER_EN; + qtest_writel(s, baseaddr + A_I2CC_FUN_CTRL, v); + once = 1; + } + + /* select device */ + qtest_writel(s, baseaddr + A_I2CD_BYTE_BUF, slave_addr << 1); + qtest_writel(s, baseaddr + A_I2CD_CMD, + A_I2CD_M_START_CMD | A_I2CD_M_RX_CMD); + + /* select the register to write to */ + qtest_writel(s, baseaddr + A_I2CD_BYTE_BUF, reg); + qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD); +} + +static uint32_t aspeed_i2c_read_n(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, size_t nbytes) +{ + uint32_t res = 0; + uint32_t v; + size_t i; + + aspeed_i2c_startup(s, baseaddr, slave_addr, reg); + + for (i = 0; i < nbytes; i++) { + qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_RX_CMD); + v = qtest_readl(s, baseaddr + A_I2CD_BYTE_BUF) >> 8; + res |= (v & 0xff) << (i * 8); + } + + qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD); + + return res; +} + +uint32_t aspeed_i2c_readl(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, uint8_t reg) +{ + return aspeed_i2c_read_n(s, baseaddr, slave_addr, reg, sizeof(uint32_t)); +} + +uint16_t aspeed_i2c_readw(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, uint8_t reg) +{ + return aspeed_i2c_read_n(s, baseaddr, slave_addr, reg, sizeof(uint16_t)); +} + +uint8_t aspeed_i2c_readb(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, uint8_t reg) +{ + return aspeed_i2c_read_n(s, baseaddr, slave_addr, reg, sizeof(uint8_t)); +} + +static void aspeed_i2c_write_n(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint32_t v, size_t nbytes) +{ + size_t i; + + aspeed_i2c_startup(s, baseaddr, slave_addr, reg); + + for (i = 0; i < nbytes; i++) { + qtest_writel(s, baseaddr + A_I2CD_BYTE_BUF, v & 0xff); + v >>= 8; + qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD); + } + + qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD); +} + +void aspeed_i2c_writel(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint32_t v) +{ + aspeed_i2c_write_n(s, baseaddr, slave_addr, reg, v, sizeof(v)); +} + +void aspeed_i2c_writew(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint16_t v) +{ + aspeed_i2c_write_n(s, baseaddr, slave_addr, reg, v, sizeof(v)); +} + +void aspeed_i2c_writeb(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint8_t v) +{ + aspeed_i2c_write_n(s, baseaddr, slave_addr, reg, v, sizeof(v)); +} diff --git a/tests/qtest/qtest_aspeed.h b/tests/qtest/qtest_aspeed.h new file mode 100644 index 0000000000..235dfaa186 --- /dev/null +++ b/tests/qtest/qtest_aspeed.h @@ -0,0 +1,41 @@ +/* + * Aspeed i2c bus interface to reading and writing to i2c device registers + * + * Copyright (c) 2023 IBM Corporation + * + * Authors: + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef QTEST_ASPEED_H +#define QTEST_ASPEED_H + +#include + +#include "libqtest.h" + +#define AST2600_ASPEED_I2C_BASE_ADDR 0x1e78a000 + +/* Implements only AST2600 I2C controller */ + +static inline uint32_t ast2600_i2c_calc_bus_addr(uint8_t bus_num) +{ + return AST2600_ASPEED_I2C_BASE_ADDR + 0x80 + bus_num * 0x80; +} + +uint8_t aspeed_i2c_readb(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, uint8_t reg); +uint16_t aspeed_i2c_readw(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, uint8_t reg); +uint32_t aspeed_i2c_readl(QTestState *s, + uint32_t baseaddr, uint8_t slave_addr, uint8_t reg); +void aspeed_i2c_writeb(QTestState *s, uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint8_t v); +void aspeed_i2c_writew(QTestState *s, uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint16_t v); +void aspeed_i2c_writel(QTestState *s, uint32_t baseaddr, uint8_t slave_addr, + uint8_t reg, uint32_t v); + +#endif From f8d64616932805c5a5efea1a6a5bfee630d0096b Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 31 Mar 2023 13:30:50 -0400 Subject: [PATCH 21/23] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it To be able to remove tpm_tis_base_addr from test cases that do not really need it move the tpm_util_tis_transmit() function into tpm-tis-utils.c and rename it to tpm_tis_transmit(). Fix a locality parameter in a test case on the way. Signed-off-by: Stefan Berger Reviewed-by: Ninad Palsule Reviewed-by: Thomas Huth Message-Id: <20230331173051.3857801-3-stefanb@linux.ibm.com> Signed-off-by: Thomas Huth --- tests/qtest/tpm-crb-swtpm-test.c | 3 -- tests/qtest/tpm-crb-test.c | 3 -- tests/qtest/tpm-tis-device-swtpm-test.c | 5 +-- tests/qtest/tpm-tis-swtpm-test.c | 5 +-- tests/qtest/tpm-tis-util.c | 47 ++++++++++++++++++++++++- tests/qtest/tpm-tis-util.h | 4 +++ tests/qtest/tpm-util.c | 45 ----------------------- tests/qtest/tpm-util.h | 3 -- 8 files changed, 56 insertions(+), 59 deletions(-) diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c index 40254f762f..ffeb1c396b 100644 --- a/tests/qtest/tpm-crb-swtpm-test.c +++ b/tests/qtest/tpm-crb-swtpm-test.c @@ -19,9 +19,6 @@ #include "tpm-tests.h" #include "hw/acpi/tpm.h" -/* Not used but needed for linking */ -uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; - typedef struct TestState { char *src_tpm_path; char *dst_tpm_path; diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c index 7b94453390..396ae3f91c 100644 --- a/tests/qtest/tpm-crb-test.c +++ b/tests/qtest/tpm-crb-test.c @@ -19,9 +19,6 @@ #include "qemu/module.h" #include "tpm-emu.h" -/* Not used but needed for linking */ -uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; - #define TPM_CMD "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00" static void tpm_crb_test(const void *data) diff --git a/tests/qtest/tpm-tis-device-swtpm-test.c b/tests/qtest/tpm-tis-device-swtpm-test.c index 8c067fddd4..517a077005 100644 --- a/tests/qtest/tpm-tis-device-swtpm-test.c +++ b/tests/qtest/tpm-tis-device-swtpm-test.c @@ -18,6 +18,7 @@ #include "libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" +#include "tpm-tis-util.h" #include "hw/acpi/tpm.h" uint64_t tpm_tis_base_addr = 0xc000000; @@ -33,7 +34,7 @@ static void tpm_tis_swtpm_test(const void *data) { const TestState *ts = data; - tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, + tpm_test_swtpm_test(ts->src_tpm_path, tpm_tis_transfer, "tpm-tis-device", MACHINE_OPTIONS); } @@ -42,7 +43,7 @@ static void tpm_tis_swtpm_migration_test(const void *data) const TestState *ts = data; tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, - tpm_util_tis_transfer, "tpm-tis-device", + tpm_tis_transfer, "tpm-tis-device", MACHINE_OPTIONS); } diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c index 11539c0a52..105e42e21d 100644 --- a/tests/qtest/tpm-tis-swtpm-test.c +++ b/tests/qtest/tpm-tis-swtpm-test.c @@ -17,6 +17,7 @@ #include "libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" +#include "tpm-tis-util.h" #include "hw/acpi/tpm.h" uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; @@ -31,7 +32,7 @@ static void tpm_tis_swtpm_test(const void *data) { const TestState *ts = data; - tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, + tpm_test_swtpm_test(ts->src_tpm_path, tpm_tis_transfer, "tpm-tis", NULL); } @@ -40,7 +41,7 @@ static void tpm_tis_swtpm_migration_test(const void *data) const TestState *ts = data; tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, - tpm_util_tis_transfer, "tpm-tis", NULL); + tpm_tis_transfer, "tpm-tis", NULL); } int main(int argc, char **argv) diff --git a/tests/qtest/tpm-tis-util.c b/tests/qtest/tpm-tis-util.c index 939893bf01..728cd3e065 100644 --- a/tests/qtest/tpm-tis-util.c +++ b/tests/qtest/tpm-tis-util.c @@ -52,7 +52,7 @@ void tpm_tis_test_check_localities(const void *data) uint32_t rid; for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | TPM_TIS_ACCESS_TPM_ESTABLISHMENT); @@ -449,3 +449,48 @@ void tpm_tis_test_check_transmit(const void *data) writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); } + +void tpm_tis_transfer(QTestState *s, + const unsigned char *req, size_t req_size, + unsigned char *rsp, size_t rsp_size) +{ + uint32_t sts; + uint16_t bcount; + size_t i; + + /* request use of locality 0 */ + qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + qtest_writel(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); + + sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS)); + bcount = (sts >> 8) & 0xffff; + g_assert_cmpint(bcount, >=, req_size); + + /* transmit command */ + for (i = 0; i < req_size; i++) { + qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO), req[i]); + } + + /* start processing */ + qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); + + uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; + do { + sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS)); + if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { + break; + } + } while (g_get_monotonic_time() < end_time); + + sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS)); + bcount = (sts >> 8) & 0xffff; + + memset(rsp, 0, rsp_size); + for (i = 0; i < bcount; i++) { + rsp[i] = qtest_readb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); + } + + /* relinquish use of locality 0 */ + qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_ACTIVE_LOCALITY); +} diff --git a/tests/qtest/tpm-tis-util.h b/tests/qtest/tpm-tis-util.h index d10efe86ae..03910a7ba7 100644 --- a/tests/qtest/tpm-tis-util.h +++ b/tests/qtest/tpm-tis-util.h @@ -20,4 +20,8 @@ void tpm_tis_test_check_access_reg_seize(const void *data); void tpm_tis_test_check_access_reg_release(const void *data); void tpm_tis_test_check_transmit(const void *data); +void tpm_tis_transfer(QTestState *s, + const unsigned char *req, size_t req_size, + unsigned char *rsp, size_t rsp_size); + #endif /* TESTS_TPM_TIS_UTIL_H */ diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c index a7efe2d0d2..1c0319e6e7 100644 --- a/tests/qtest/tpm-util.c +++ b/tests/qtest/tpm-util.c @@ -51,51 +51,6 @@ void tpm_util_crb_transfer(QTestState *s, qtest_memread(s, raddr, rsp, rsp_size); } -void tpm_util_tis_transfer(QTestState *s, - const unsigned char *req, size_t req_size, - unsigned char *rsp, size_t rsp_size) -{ - uint32_t sts; - uint16_t bcount; - size_t i; - - /* request use of locality 0 */ - qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - qtest_writel(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); - - sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS)); - bcount = (sts >> 8) & 0xffff; - g_assert_cmpint(bcount, >=, req_size); - - /* transmit command */ - for (i = 0; i < req_size; i++) { - qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO), req[i]); - } - - /* start processing */ - qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); - - uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; - do { - sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS)); - if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { - break; - } - } while (g_get_monotonic_time() < end_time); - - sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS)); - bcount = (sts >> 8) & 0xffff; - - memset(rsp, 0, rsp_size); - for (i = 0; i < bcount; i++) { - rsp[i] = qtest_readb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); - } - - /* relinquish use of locality 0 */ - qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_ACTIVE_LOCALITY); -} - void tpm_util_startup(QTestState *s, tx_func *tx) { unsigned char buffer[1024]; diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h index 80720afac0..0cb28dd6e5 100644 --- a/tests/qtest/tpm-util.h +++ b/tests/qtest/tpm-util.h @@ -27,9 +27,6 @@ typedef void (tx_func)(QTestState *s, void tpm_util_crb_transfer(QTestState *s, const unsigned char *req, size_t req_size, unsigned char *rsp, size_t rsp_size); -void tpm_util_tis_transfer(QTestState *s, - const unsigned char *req, size_t req_size, - unsigned char *rsp, size_t rsp_size); void tpm_util_startup(QTestState *s, tx_func *tx); void tpm_util_pcrextend(QTestState *s, tx_func *tx); From bcbbd95d2ae002242ebf971d6e1e9aefb75ac8e2 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 31 Mar 2023 13:30:51 -0400 Subject: [PATCH 22/23] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test case for the TPM TIS I2C device exercising most of its functionality, including localities. Signed-off-by: Stefan Berger Tested-by: Cédric Le Goater Tested-by: Ninad Palsule Message-Id: <20230331173051.3857801-4-stefanb@linux.ibm.com> Signed-off-by: Thomas Huth --- tests/qtest/meson.build | 3 + tests/qtest/tpm-tis-i2c-test.c | 663 +++++++++++++++++++++++++++++++++ 2 files changed, 666 insertions(+) create mode 100644 tests/qtest/tpm-tis-i2c-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 85ea4e8d99..cfc66ade6f 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -200,6 +200,7 @@ qtests_arm = \ (config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed : []) + \ (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \ (config_all_devices.has_key('CONFIG_GENERIC_LOADER') ? ['hexloader-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ ['arm-cpu-features', 'microbit-test', 'test-arm-mptimer', @@ -212,6 +213,7 @@ qtests_aarch64 = \ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ ['arm-cpu-features', 'numa-test', 'boot-serial-test', @@ -304,6 +306,7 @@ qtests = { 'tpm-crb-test': [io, tpmemu_files], 'tpm-tis-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'], 'tpm-tis-test': [io, tpmemu_files, 'tpm-tis-util.c'], + 'tpm-tis-i2c-test': [io, tpmemu_files, 'qtest_aspeed.c'], 'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'], 'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'], 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), diff --git a/tests/qtest/tpm-tis-i2c-test.c b/tests/qtest/tpm-tis-i2c-test.c new file mode 100644 index 0000000000..7a590ac551 --- /dev/null +++ b/tests/qtest/tpm-tis-i2c-test.c @@ -0,0 +1,663 @@ +/* + * QTest testcases for TPM TIS on I2C (derived from TPM TIS test) + * + * Copyright (c) 2023 IBM Corporation + * Copyright (c) 2023 Red Hat, Inc. + * + * Authors: + * Stefan Berger + * Marc-André Lureau + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include + +#include "libqtest-single.h" +#include "hw/acpi/tpm.h" +#include "hw/pci/pci_ids.h" +#include "qtest_aspeed.h" +#include "tpm-emu.h" + +#define DEBUG_TIS_TEST 0 + +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_TIS_TEST) { \ + printf(fmt, ## __VA_ARGS__); \ + } \ +} while (0) + +#define DPRINTF_ACCESS \ + DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ + __func__, __LINE__, locty, l, access, pending_request_flag) + +#define DPRINTF_STS \ + DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) + +#define I2C_SLAVE_ADDR 0x2e +#define I2C_DEV_BUS_NUM 10 + +static const uint8_t TPM_CMD[12] = + "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; + +static uint32_t aspeed_bus_addr; + +static uint8_t cur_locty = 0xff; + +static void tpm_tis_i2c_set_locty(uint8_t locty) +{ + if (cur_locty != locty) { + cur_locty = locty; + aspeed_i2c_writeb(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, + TPM_I2C_REG_LOC_SEL, locty); + } +} + +static uint8_t tpm_tis_i2c_readb(uint8_t locty, uint8_t reg) +{ + tpm_tis_i2c_set_locty(locty); + return aspeed_i2c_readb(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg); +} + +static uint16_t tpm_tis_i2c_readw(uint8_t locty, uint8_t reg) +{ + tpm_tis_i2c_set_locty(locty); + return aspeed_i2c_readw(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg); +} + +static uint32_t tpm_tis_i2c_readl(uint8_t locty, uint8_t reg) +{ + tpm_tis_i2c_set_locty(locty); + return aspeed_i2c_readl(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg); +} + +static void tpm_tis_i2c_writeb(uint8_t locty, uint8_t reg, uint8_t v) +{ + if (reg != TPM_I2C_REG_LOC_SEL) { + tpm_tis_i2c_set_locty(locty); + } + aspeed_i2c_writeb(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v); +} + +static void tpm_tis_i2c_writel(uint8_t locty, uint8_t reg, uint32_t v) +{ + if (reg != TPM_I2C_REG_LOC_SEL) { + tpm_tis_i2c_set_locty(locty); + } + aspeed_i2c_writel(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v); +} + +static void tpm_tis_i2c_test_basic(const void *data) +{ + uint8_t access; + uint32_t v, v2; + + /* + * All register accesses below must work without locality 0 being the + * active locality. Therefore, ensure access is released. + */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* read interrupt capability -- none are supported */ + v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY); + g_assert_cmpint(v, ==, 0); + + /* try to enable all interrupts */ + tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff); + v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE); + /* none could be enabled */ + g_assert_cmpint(v, ==, 0); + + /* enable csum */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED); + /* check csum enable register has bit 0 set */ + v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE); + g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED); + /* reading it as 32bit register returns same result */ + v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE); + g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED); + + /* disable csum */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0); + /* check csum enable register has bit 0 clear */ + v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE); + g_assert_cmpint(v, ==, 0); + + /* write to unsupported register '1' */ + tpm_tis_i2c_writel(0, 1, 0x12345678); + v = tpm_tis_i2c_readl(0, 1); + g_assert_cmpint(v, ==, 0xffffffff); + + /* request use of locality */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE); + + /* read byte from STS + 3 */ + v = tpm_tis_i2c_readb(0, TPM_I2C_REG_STS + 3); + g_assert_cmpint(v, ==, 0); + + /* check STS after writing to STS + 3 */ + v = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + tpm_tis_i2c_writeb(0, TPM_I2C_REG_STS + 3, 0xf); + v2 = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + g_assert_cmpint(v, ==, v2); + + /* release access */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + + /* select locality 5 -- must not be possible */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_LOC_SEL, 5); + v = tpm_tis_i2c_readb(0, TPM_I2C_REG_LOC_SEL); + g_assert_cmpint(v, ==, 0); +} + +static void tpm_tis_i2c_test_check_localities(const void *data) +{ + uint8_t locty, l; + uint8_t access; + uint32_t capability, i2c_cap; + uint32_t didvid; + uint32_t rid; + + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + capability = tpm_tis_i2c_readl(locty, TPM_I2C_REG_INTF_CAPABILITY); + i2c_cap = (TPM_I2C_CAP_INTERFACE_TYPE | + TPM_I2C_CAP_INTERFACE_VER | + TPM_I2C_CAP_TPM2_FAMILY | + TPM_I2C_CAP_LOCALITY_CAP | + TPM_I2C_CAP_BUS_SPEED | + TPM_I2C_CAP_DEV_ADDR_CHANGE); + g_assert_cmpint(capability, ==, i2c_cap); + + didvid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_DID_VID); + g_assert_cmpint(didvid, ==, (1 << 16) | PCI_VENDOR_ID_IBM); + + rid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_RID); + g_assert_cmpint(rid, !=, 0); + g_assert_cmpint(rid, !=, 0xffffffff); + + /* locality selection must be at locty */ + l = tpm_tis_i2c_readb(locty, TPM_I2C_REG_LOC_SEL); + g_assert_cmpint(l, ==, locty); + } +} + +static void tpm_tis_i2c_test_check_access_reg(const void *data) +{ + uint8_t locty; + uint8_t access; + + /* do not test locality 4 (hw only) */ + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of locality */ + tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_REQUEST_USE); + + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* release access */ + tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } +} + +/* + * Test case for seizing access by a higher number locality + */ +static void tpm_tis_i2c_test_check_access_reg_seize(const void *data) +{ + int locty, l; + uint8_t access; + uint8_t pending_request_flag; + + /* do not test locality 4 (hw only) */ + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { + pending_request_flag = 0; + + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of locality */ + tpm_tis_i2c_writeb(locty, + TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE); + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* lower localities cannot seize access */ + for (l = 0; l < locty; l++) { + /* lower locality is not active */ + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* try to request use from 'l' */ + tpm_tis_i2c_writeb(l, + TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_REQUEST_USE); + + /* + * requesting use from 'l' was not possible; + * we must see REQUEST_USE and possibly PENDING_REQUEST + */ + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* + * locality 'locty' must be unchanged; + * we must see PENDING_REQUEST + */ + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_PENDING_REQUEST | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* try to seize from 'l' */ + tpm_tis_i2c_writeb(l, + TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE); + /* seize from 'l' was not possible */ + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* locality 'locty' must be unchanged */ + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_PENDING_REQUEST | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* + * on the next loop we will have a PENDING_REQUEST flag + * set for locality 'l' + */ + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; + } + + /* + * higher localities can 'seize' access but not 'request use'; + * note: this will activate first l+1, then l+2 etc. + */ + for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { + /* try to 'request use' from 'l' */ + tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_REQUEST_USE); + + /* + * requesting use from 'l' was not possible; we should see + * REQUEST_USE and may see PENDING_REQUEST + */ + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* + * locality 'l-1' must be unchanged; we should always + * see PENDING_REQUEST from 'l' requesting access + */ + access = tpm_tis_i2c_readb(l - 1, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_PENDING_REQUEST | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* try to seize from 'l' */ + tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE); + + /* seize from 'l' was possible */ + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* l - 1 should show that it has BEEN_SEIZED */ + access = tpm_tis_i2c_readb(l - 1, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_BEEN_SEIZED | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* clear the BEEN_SEIZED flag and make sure it's gone */ + tpm_tis_i2c_writeb(l - 1, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_BEEN_SEIZED); + + access = tpm_tis_i2c_readb(l - 1, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } + + /* + * PENDING_REQUEST will not be set if locty = 0 since all localities + * were active; in case of locty = 1, locality 0 will be active + * but no PENDING_REQUEST anywhere + */ + if (locty <= 1) { + pending_request_flag = 0; + } + + /* release access from l - 1; this activates locty - 1 */ + l--; + + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + + DPRINTF("%s: %d: relinquishing control on l = %d\n", + __func__, __LINE__, l); + tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + for (l = locty - 1; l >= 0; l--) { + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* release this locality */ + tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + + if (l == 1) { + pending_request_flag = 0; + } + } + + /* no locality may be active now */ + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } + } +} + +/* + * Test case for getting access when higher number locality relinquishes access + */ +static void tpm_tis_i2c_test_check_access_reg_release(const void *data) +{ + int locty, l; + uint8_t access; + uint8_t pending_request_flag; + + /* do not test locality 4 (hw only) */ + for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { + pending_request_flag = 0; + + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of locality */ + tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_REQUEST_USE); + access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of all other localities */ + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { + if (l == locty) { + continue; + } + /* + * request use of locality 'l' -- we MUST see REQUEST USE and + * may see PENDING_REQUEST + */ + tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_REQUEST_USE); + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; + } + /* release locality 'locty' */ + tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + /* + * highest locality should now be active; release it and make sure the + * next higest locality is active afterwards + */ + for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { + if (l == locty) { + continue; + } + /* 'l' should be active now */ + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + /* 'l' relinquishes access */ + tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS); + DPRINTF_ACCESS; + if (l == 1 || (locty <= 1 && l == 2)) { + pending_request_flag = 0; + } + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } + } +} + +/* + * Test case for transmitting packets + */ +static void tpm_tis_i2c_test_check_transmit(const void *data) +{ + const TPMTestState *s = data; + uint8_t access; + uint32_t sts, v; + uint16_t bcount, csum, bcount2; + size_t i; + + /* enable csum */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED); + /* check csum enable register has bit 0 set */ + v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE); + g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED); + /* reading it as 32bit register returns same result */ + v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE); + g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED); + + /* request use of locality 0 */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE); + access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + DPRINTF_STS; + + g_assert_cmpint(sts & 0xff, ==, 0); + + bcount = (sts >> 8) & 0xffff; + g_assert_cmpint(bcount, >=, 128); + + /* read bcount from STS + 1 must work also */ + bcount2 = tpm_tis_i2c_readw(0, TPM_I2C_REG_STS + 1); + g_assert_cmpint(bcount, ==, bcount2); + + /* ic2 must have bits 26-31 zero */ + g_assert_cmpint(sts & (0x1f << 26), ==, 0); + + tpm_tis_i2c_writel(0, TPM_I2C_REG_STS, TPM_TIS_STS_COMMAND_READY); + sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + DPRINTF_STS; + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); + + /* transmit command */ + for (i = 0; i < sizeof(TPM_CMD); i++) { + tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_FIFO, TPM_CMD[i]); + sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + DPRINTF_STS; + if (i < sizeof(TPM_CMD) - 1) { + g_assert_cmpint(sts & 0xff, ==, + TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); + } else { + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); + } + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); + } + /* read the checksum */ + csum = tpm_tis_i2c_readw(0, TPM_I2C_REG_DATA_CSUM_GET); + g_assert_cmpint(csum, ==, 0x6733); + + /* start processing */ + tpm_tis_i2c_writeb(0, TPM_I2C_REG_STS, TPM_TIS_STS_TPM_GO); + + uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; + do { + sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { + break; + } + } while (g_get_monotonic_time() < end_time); + + sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + DPRINTF_STS; + g_assert_cmpint(sts & 0xff, == , + TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); + bcount = (sts >> 8) & 0xffff; + + /* read response */ + uint8_t tpm_msg[sizeof(struct tpm_hdr)]; + g_assert_cmpint(sizeof(tpm_msg), ==, bcount); + + for (i = 0; i < sizeof(tpm_msg); i++) { + tpm_msg[i] = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_FIFO); + sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS); + DPRINTF_STS; + if (sts & TPM_TIS_STS_DATA_AVAILABLE) { + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); + } + } + g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); + + /* relinquish use of locality 0 */ + tpm_tis_i2c_writeb(0, + TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS); +} + +int main(int argc, char **argv) +{ + int ret; + char *args; + char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-i2c-test.XXXXXX", NULL); + GThread *thread; + TPMTestState test; + + module_call_init(MODULE_INIT_QOM); + g_test_init(&argc, &argv, NULL); + + test.addr = g_new0(SocketAddress, 1); + test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; + test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); + g_mutex_init(&test.data_mutex); + g_cond_init(&test.data_cond); + test.data_cond_signal = false; + test.tpm_version = TPM_VERSION_2_0; + + thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); + tpm_emu_test_wait_cond(&test); + + aspeed_bus_addr = ast2600_i2c_calc_bus_addr(I2C_DEV_BUS_NUM); + + args = g_strdup_printf( + "-machine rainier-bmc -accel tcg " + "-chardev socket,id=chr,path=%s " + "-tpmdev emulator,id=tpm0,chardev=chr " + "-device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.%d,address=0x%x", + test.addr->u.q_unix.path, + I2C_DEV_BUS_NUM, + I2C_SLAVE_ADDR); + qtest_start(args); + + qtest_add_data_func("/tpm-tis-i2c/test_basic", &test, + tpm_tis_i2c_test_basic); + + qtest_add_data_func("/tpm-tis-i2c/test_check_localities", &test, + tpm_tis_i2c_test_check_localities); + + qtest_add_data_func("/tpm-tis-i2c/check_access_reg", &test, + tpm_tis_i2c_test_check_access_reg); + + qtest_add_data_func("/tpm-tis-i2c/check_access_reg_seize", &test, + tpm_tis_i2c_test_check_access_reg_seize); + + qtest_add_data_func("/tpm-tis-i2c/check_access_reg_release", &test, + tpm_tis_i2c_test_check_access_reg_release); + + qtest_add_data_func("/tpm-tis-i2c/test_check_transmit", &test, + tpm_tis_i2c_test_check_transmit); + + ret = g_test_run(); + + qtest_end(); + + g_thread_join(thread); + g_unlink(test.addr->u.q_unix.path); + qapi_free_SocketAddress(test.addr); + g_rmdir(tmp_path); + g_free(tmp_path); + g_free(args); + return ret; +} From ec6fb1c8cd8d55c3d2a34cacfea6df0fe6c76057 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 19 Apr 2023 16:45:53 +0200 Subject: [PATCH 23/23] tests/vm/freebsd: Update to FreeBSD 13.2 According to QEMU's support policy, we stop supporting the previous major release two years after the the new major release has been published. So we can stop testing FreeBSD 12 now and should switch our FreeBSD VM to version 13 instead. Some changes are needed for this update: The downloadable .ISO images do not use the serial port as console by default anymore, so they are not usable in the same way as with FreeBSD 12. Fortunately, the FreeBSD project now also offers some pre-installed CI images that have the serial console enabled, so we can use those now, with the benefit that we can skip almost all parts of the previous installation process. Message-Id: <20230419144553.719749-1-thuth@redhat.com> Reviewed-by: Warner Losh Signed-off-by: Thomas Huth --- tests/vm/freebsd | 95 +++++++++++------------------------------------- 1 file changed, 22 insertions(+), 73 deletions(-) diff --git a/tests/vm/freebsd b/tests/vm/freebsd index ba2ba23d24..11de6473f4 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -28,15 +28,15 @@ class FreeBSDVM(basevm.BaseVM): name = "freebsd" arch = "x86_64" - link = "https://download.freebsd.org/ftp/releases/ISO-IMAGES/12.4/FreeBSD-12.4-RELEASE-amd64-disc1.iso.xz" - csum = "1dcf6446e31bf3f81b582e9aba3319a258c29a937a2af6138ee4b181ed719a87" + link = "https://download.freebsd.org/releases/CI-IMAGES/13.2-RELEASE/amd64/Latest/FreeBSD-13.2-RELEASE-amd64-BASIC-CI.raw.xz" + csum = "a4fb3b6c7b75dd4d58fb0d75e4caf72844bffe0ca00e66459c028b198ffb3c0e" size = "20G" pkgs = [ # build tools "git", "pkgconf", "bzip2", - "python37", + "python39", "ninja", # gnu tools @@ -78,72 +78,42 @@ class FreeBSDVM(basevm.BaseVM): mkdir src build; cd src; tar -xf /dev/vtbd1; cd ../build - ../src/configure --python=python3.7 {configure_opts}; + ../src/configure --python=python3.9 {configure_opts}; gmake --output-sync -j{jobs} {target} {verbose}; """ - def console_boot_serial(self): - self.console_wait_send("Autoboot", "3") - self.console_wait_send("OK", "set console=comconsole\n") - self.console_wait_send("OK", "boot\n") - def build_image(self, img): - self.print_step("Downloading install iso") + self.print_step("Downloading disk image") cimg = self._download_with_cache(self.link, sha256sum=self.csum) - img_tmp = img + ".tmp" - iso = img + ".install.iso" - iso_xz = iso + ".xz" + tmp_raw = img + ".tmp.raw" + tmp_raw_xz = tmp_raw + ".xz" + img_tmp = img + ".tmp.qcow2" - self.print_step("Preparing iso and disk image") - subprocess.check_call(["cp", "-f", cimg, iso_xz]) - subprocess.check_call(["xz", "-dvf", iso_xz]) - self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size) + self.print_step("Preparing disk image") + subprocess.check_call(["cp", "-f", cimg, tmp_raw_xz]) + subprocess.check_call(["xz", "-dvf", tmp_raw_xz]) + self.exec_qemu_img("convert", "-O", "qcow2", tmp_raw, img_tmp) + self.exec_qemu_img("resize", img_tmp, self.size) + os.remove(tmp_raw) - self.print_step("Booting installer") + self.print_step("Preparing disk image") self.boot(img_tmp, extra_args = [ "-machine", "graphics=off", - "-device", "VGA", - "-cdrom", iso + "-vga", "none" ]) self.console_init() - self.console_boot_serial() - self.console_wait_send("Console type", "xterm\n") + self.console_wait_send("login:", "root\n") + self.console_wait_send("~ #", "service growfs onestart\n") - # pre-install configuration - self.console_wait_send("Welcome", "\n") - self.console_wait_send("Keymap Selection", "\n") - self.console_wait_send("Set Hostname", "freebsd\n") - self.console_wait_send("Distribution Select", "\n") - self.console_wait_send("Partitioning", "\n") - self.console_wait_send("Partition", "\n") - self.console_wait_send("Scheme", "\n") - self.console_wait_send("Editor", "f") - self.console_wait_send("Confirmation", "c") - - self.print_step("Installation started now, this will take a while") - - # post-install configuration + # root user + self.console_wait_send("~ #", "passwd\n") self.console_wait("New Password:") self.console_send("%s\n" % self._config["root_pass"]) self.console_wait("Retype New Password:") self.console_send("%s\n" % self._config["root_pass"]) - self.console_wait_send("Network Configuration", "\n") - self.console_wait_send("IPv4", "y") - self.console_wait_send("DHCP", "y") - self.console_wait_send("IPv6", "n") - self.console_wait_send("Resolver", "\n") - - self.console_wait_send("Time Zone Selector", "0\n") - self.console_wait_send("Confirmation", "y") - self.console_wait_send("Time & Date", "\n") - self.console_wait_send("Time & Date", "\n") - - self.console_wait_send("System Configuration", "\n") - self.console_wait_send("System Hardening", "\n") - # qemu user - self.console_wait_send("Add User Accounts", "y") + self.console_wait_send("~ #", "adduser\n") self.console_wait("Username") self.console_send("%s\n" % self._config["guest_user"]) self.console_wait("Full name") @@ -165,13 +135,7 @@ class FreeBSDVM(basevm.BaseVM): self.console_wait_send("Lock out", "\n") self.console_wait_send("OK", "yes\n") self.console_wait_send("Add another user", "no\n") - - self.console_wait_send("Final Configuration", "\n") - self.console_wait_send("Manual Configuration", "\n") - self.console_wait_send("Complete", "\n") - - self.print_step("Installation finished, rebooting") - self.console_boot_serial() + self.console_wait_send("~ #", "exit\n") # setup qemu user prompt = "$" @@ -183,35 +147,20 @@ class FreeBSDVM(basevm.BaseVM): self.console_ssh_init(prompt, "root", self._config["root_pass"]) self.console_sshd_config(prompt) - # setup serial console - self.console_wait(prompt) - self.console_send("echo 'console=comconsole' >> /boot/loader.conf\n") - - # setup boot delay - self.console_wait(prompt) - self.console_send("echo 'autoboot_delay=1' >> /boot/loader.conf\n") - # setup virtio-blk #1 (tarfile) self.console_wait(prompt) self.console_send("echo 'chmod 666 /dev/vtbd1' >> /etc/rc.local\n") - self.print_step("Configuration finished, rebooting") - self.console_wait_send(prompt, "reboot\n") - self.console_wait("login:") - self.wait_ssh() - self.print_step("Installing packages") self.ssh_root_check("pkg install -y %s\n" % " ".join(self.pkgs)) # shutdown self.ssh_root(self.poweroff) - self.console_wait("Uptime:") self.wait() if os.path.exists(img): os.remove(img) os.rename(img_tmp, img) - os.remove(iso) self.print_step("All done") if __name__ == "__main__":