Browse Source

* Check functional tests with pylint

* update copyright year to 2026
 * Some more universal-binary work for the s390x code done by Philippe
 * Fix reverse debugging for s390x and add a functional test for it
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmlk81cRHHRodXRoQHJl
 ZGhhdC5jb20ACgkQLtnXdP5wLbWxhxAAlvaTwC7trSsFY3sTMwenG0GHfg0M840H
 vYXHm69uHigT4IyC2pXOjCN0Yq9zujCymtUIWOKY8l+Hx/x5tgi5fKhOXqqZBhJP
 KyBKZqJx3cVZC54qlNWF0vxSYCi32wi6xQmVlMYtbBZPfbMfY1Vi55PAknpXCWjv
 YfBB72LQhS3uPBLOi2Dg3mkGq9+cqHoAVCDVguOBx0N4SdkotvbKrG4XOhFfzjVu
 VrLgwF2LBLQzlU2JZ/b2u1IOSju67c0qW29dx86p5n6JZdLqNhsOjQ81ToHpQML2
 S/X2Nv0uyZTSzjdriBvkyOnM6L35wpZ2qyPrRekfnwzUNKEyHN9b+WTqAZdvCrm1
 eKrs87HQ7u3XUu3lR43fFCVlAgpstsF2I9UyyiMMEqGlKAjllDzgy7U3SYaP04Zm
 pgv7cLt1jgh5GoLB7TC/XRdy1P7Ya1cZ76tL2Uj93CF4w7E2vtHtVzCA6YQk9kVJ
 jn9pxjYXw/qsoQgM2Ze7UI/d5MYqVHVPK83T5natq1sXf9ardmf2OGQWLrp1JaUl
 O8xeVpMR08tElxPlcEL+3zd5YAw4QrNJ9D7GhfJQWKOgnOkT/4Kslcyqp8wLP4/D
 oeNVrv/aEXA8Lf+ozHyIEejmmWJnmgHlAnfL+wi9KV1JzWAsskg5ClR8G3ZzAa69
 CUnS7mOSnsw=
 =N/we
 -----END PGP SIGNATURE-----

Merge tag 'pull-request-2026-01-12' of https://gitlab.com/thuth/qemu into staging

* Check functional tests with pylint
* update copyright year to 2026
* Some more universal-binary work for the s390x code done by Philippe
* Fix reverse debugging for s390x and add a functional test for it

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmlk81cRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbWxhxAAlvaTwC7trSsFY3sTMwenG0GHfg0M840H
# vYXHm69uHigT4IyC2pXOjCN0Yq9zujCymtUIWOKY8l+Hx/x5tgi5fKhOXqqZBhJP
# KyBKZqJx3cVZC54qlNWF0vxSYCi32wi6xQmVlMYtbBZPfbMfY1Vi55PAknpXCWjv
# YfBB72LQhS3uPBLOi2Dg3mkGq9+cqHoAVCDVguOBx0N4SdkotvbKrG4XOhFfzjVu
# VrLgwF2LBLQzlU2JZ/b2u1IOSju67c0qW29dx86p5n6JZdLqNhsOjQ81ToHpQML2
# S/X2Nv0uyZTSzjdriBvkyOnM6L35wpZ2qyPrRekfnwzUNKEyHN9b+WTqAZdvCrm1
# eKrs87HQ7u3XUu3lR43fFCVlAgpstsF2I9UyyiMMEqGlKAjllDzgy7U3SYaP04Zm
# pgv7cLt1jgh5GoLB7TC/XRdy1P7Ya1cZ76tL2Uj93CF4w7E2vtHtVzCA6YQk9kVJ
# jn9pxjYXw/qsoQgM2Ze7UI/d5MYqVHVPK83T5natq1sXf9ardmf2OGQWLrp1JaUl
# O8xeVpMR08tElxPlcEL+3zd5YAw4QrNJ9D7GhfJQWKOgnOkT/4Kslcyqp8wLP4/D
# oeNVrv/aEXA8Lf+ozHyIEejmmWJnmgHlAnfL+wi9KV1JzWAsskg5ClR8G3ZzAa69
# CUnS7mOSnsw=
# =N/we
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 13 Jan 2026 12:12:55 AM AEDT
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [unknown]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [unknown]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* tag 'pull-request-2026-01-12' of https://gitlab.com/thuth/qemu:
  tests/functional/s390x: Add reverse debugging test for s390x
  target/s390x: Fix infinite loop during replay
  target/s390x: Un-inline s390_is_pv()
  target/s390x: Simplify S390_ADAPTER_SUPPRESSIBLE definition
  target/s390x: Remove unused 'gdbstub/helpers.h' header in helper.c
  target/s390x: Replace target_ulong -> uint64_t in gdb_write_register()
  target/s390x: Use vaddr for $pc in get_next_pc()
  target/s390x: Restrict WatchPoint API to TCG
  docs: update copyright year to 2026
  tests/functional: Add a generic test that checks the files with pylint
  tests/functional/aarch64/test_smmu: Silence warning from pylint
  tests/functional/aarch64/test_virt_gpu: Fix style issues
  tests/functional/ppc64/test_hv: Silence warnings reported by pylint
  tests/functional/mips/test_malta: Silence warnings reported by pylint
  tests/functional: Add a pylintrc file

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
pull/316/head
Richard Henderson 7 months ago
parent
commit
07d73947d0
  1. 2
      MAINTAINERS
  2. 2
      docs/conf.py
  3. 5
      hw/s390x/tod.c
  4. 2
      include/hw/s390x/css.h
  5. 2
      include/qemu/help-texts.h
  6. 11
      stubs/async-run-on-cpu.c
  7. 8
      stubs/cpus-queue.c
  8. 2
      stubs/meson.build
  9. 30
      target/s390x/cpu.c
  10. 6
      target/s390x/cpu.h
  11. 2
      target/s390x/gdbstub.c
  12. 39
      target/s390x/helper.c
  13. 2
      target/s390x/kvm/kvm.c
  14. 18
      target/s390x/kvm/pv.c
  15. 24
      target/s390x/kvm/pv.h
  16. 4
      target/s390x/machine.c
  17. 2
      target/s390x/s390x-internal.h
  18. 85
      target/s390x/tcg/debug.c
  19. 32
      target/s390x/tcg/excp_helper.c
  20. 3
      target/s390x/tcg/meson.build
  21. 5
      target/s390x/tcg/tcg_s390x.h
  22. 5
      target/s390x/tcg/translate.c
  23. 1
      tests/functional/aarch64/test_smmu.py
  24. 20
      tests/functional/aarch64/test_virt_gpu.py
  25. 1
      tests/functional/generic/meson.build
  26. 41
      tests/functional/generic/test_linters.py
  27. 8
      tests/functional/mips/test_malta.py
  28. 10
      tests/functional/ppc64/test_hv.py
  29. 84
      tests/functional/pylintrc
  30. 4
      tests/functional/reverse_debugging.py
  31. 1
      tests/functional/s390x/meson.build
  32. 21
      tests/functional/s390x/test_reverse_debug.py
  33. 30
      util/qemu-timer.c

2
MAINTAINERS

@ -4461,6 +4461,8 @@ F: docs/devel/testing/functional.rst
F: scripts/clean_functional_cache.py
F: tests/functional/meson.build
F: tests/functional/generic/meson.build
F: tests/functional/generic/test_linters.py
F: tests/functional/pylintrc
F: tests/functional/qemu_test/
Windows Hosted Continuous Integration

2
docs/conf.py

@ -92,7 +92,7 @@ default_role = 'any'
# General information about the project.
project = u'QEMU'
copyright = u'2025, The QEMU Project Developers'
copyright = u'2026, The QEMU Project Developers'
author = u'The QEMU Project Developers'
# The version info for the project you're documenting, acts as replacement for

5
hw/s390x/tod.c

@ -72,6 +72,11 @@ static void s390_tod_save(QEMUFile *f, void *opaque)
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_PRESENT);
qemu_put_byte(f, tod.high);
qemu_put_be64(f, tod.low);
tdc->set(td, &tod, &err);
if (err) {
warn_report_err(err);
}
}
static int s390_tod_load(QEMUFile *f, void *opaque, int version_id)

2
include/hw/s390x/css.h

@ -238,6 +238,8 @@ uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc);
void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable,
uint8_t flags, Error **errp);
#define S390_ADAPTER_SUPPRESSIBLE 0x01
SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
uint16_t schid);
bool css_subch_visible(SubchDev *sch);

2
include/qemu/help-texts.h

@ -2,7 +2,7 @@
#define QEMU_HELP_TEXTS_H
/* Copyright string for -version arguments, About dialogs, etc */
#define QEMU_COPYRIGHT "Copyright (c) 2003-2025 " \
#define QEMU_COPYRIGHT "Copyright (c) 2003-2026 " \
"Fabrice Bellard and the QEMU Project developers"
/* Bug reporting information for --help arguments, About dialogs, etc */

11
stubs/async-run-on-cpu.c

@ -0,0 +1,11 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "hw/core/cpu.h"
void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
{
abort();
}

8
stubs/cpus-queue.c

@ -0,0 +1,8 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "hw/core/cpu.h"
CPUTailQ cpus_queue = QTAILQ_HEAD_INITIALIZER(cpus_queue);

2
stubs/meson.build

@ -41,6 +41,8 @@ if have_block or have_ga
stub_ss.add(files('monitor-internal.c'))
stub_ss.add(files('qmp-command-available.c'))
stub_ss.add(files('qmp-quit.c'))
stub_ss.add(files('async-run-on-cpu.c'))
stub_ss.add(files('cpus-queue.c'))
endif
if have_block or have_user

30
target/s390x/cpu.c

@ -40,6 +40,7 @@
#include "system/reset.h"
#endif
#include "hw/s390x/cpu-topology.h"
#include "tcg/tcg_s390x.h"
#define CR0_RESET 0xE0UL
#define CR14_RESET 0xC2000000UL;
@ -74,26 +75,25 @@ void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
env->psw.mask = mask;
/* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
if (!tcg_enabled()) {
return;
}
env->cc_op = (mask >> 44) & 3;
if (tcg_enabled()) {
env->cc_op = (mask >> 44) & 3;
#ifndef CONFIG_USER_ONLY
if (is_early_exception_psw(mask, addr)) {
env->int_pgm_ilen = 0;
trigger_pgm_exception(env, PGM_SPECIFICATION);
return;
}
if (is_early_exception_psw(mask, addr)) {
env->int_pgm_ilen = 0;
trigger_pgm_exception(env, PGM_SPECIFICATION);
return;
}
if ((old_mask ^ mask) & PSW_MASK_PER) {
s390_cpu_recompute_watchpoints(env_cpu(env));
}
if ((old_mask ^ mask) & PSW_MASK_PER) {
s390_cpu_recompute_watchpoints(env_cpu(env));
}
if (mask & PSW_MASK_WAIT) {
s390_handle_wait(env_archcpu(env));
}
if (mask & PSW_MASK_WAIT) {
s390_handle_wait(env_archcpu(env));
}
#endif
}
}
uint64_t s390_cpu_get_psw_mask(CPUS390XState *env)

6
target/s390x/cpu.h

@ -39,12 +39,6 @@
#define S390_MAX_CPUS 248
#ifndef CONFIG_KVM
#define S390_ADAPTER_SUPPRESSIBLE 0x01
#else
#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE
#endif
typedef struct PSW {
uint64_t mask;
uint64_t addr;

2
target/s390x/gdbstub.c

@ -46,7 +46,7 @@ int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
CPUS390XState *env = cpu_env(cs);
target_ulong tmpl = ldq_be_p(mem_buf);
uint64_t tmpl = ldq_be_p(mem_buf);
switch (n) {
case S390_PSWM_REGNUM:

39
target/s390x/helper.c

@ -21,7 +21,6 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "s390x-internal.h"
#include "gdbstub/helpers.h"
#include "qemu/timer.h"
#include "hw/s390x/ioinst.h"
#include "system/hw_accel.h"
@ -143,41 +142,3 @@ void do_restart_interrupt(CPUS390XState *env)
s390_cpu_set_psw(env, mask, addr);
}
void s390_cpu_recompute_watchpoints(CPUState *cs)
{
const int wp_flags = BP_CPU | BP_MEM_WRITE | BP_STOP_BEFORE_ACCESS;
CPUS390XState *env = cpu_env(cs);
/* We are called when the watchpoints have changed. First
remove them all. */
cpu_watchpoint_remove_all(cs, BP_CPU);
/* Return if PER is not enabled */
if (!(env->psw.mask & PSW_MASK_PER)) {
return;
}
/* Return if storage-alteration event is not enabled. */
if (!(env->cregs[9] & PER_CR9_EVENT_STORE)) {
return;
}
if (env->cregs[10] == 0 && env->cregs[11] == -1LL) {
/* We can't create a watchoint spanning the whole memory range, so
split it in two parts. */
cpu_watchpoint_insert(cs, 0, 1ULL << 63, wp_flags, NULL);
cpu_watchpoint_insert(cs, 1ULL << 63, 1ULL << 63, wp_flags, NULL);
} else if (env->cregs[10] > env->cregs[11]) {
/* The address range loops, create two watchpoints. */
cpu_watchpoint_insert(cs, env->cregs[10], -env->cregs[10],
wp_flags, NULL);
cpu_watchpoint_insert(cs, 0, env->cregs[11] + 1, wp_flags, NULL);
} else {
/* Default case, create a single watchpoint. */
cpu_watchpoint_insert(cs, env->cregs[10],
env->cregs[11] - env->cregs[10] + 1,
wp_flags, NULL);
}
}

2
target/s390x/kvm/kvm.c

@ -2082,6 +2082,8 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
return r;
}
QEMU_BUILD_BUG_ON(S390_ADAPTER_SUPPRESSIBLE != KVM_S390_ADAPTER_SUPPRESSIBLE);
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
uint64_t address, uint32_t data, PCIDevice *dev)
{

18
target/s390x/kvm/pv.c

@ -25,6 +25,24 @@
#include "target/s390x/kvm/kvm_s390x.h"
#include "target/s390x/kvm/pv.h"
bool s390_is_pv(void)
{
static S390CcwMachineState *ccw;
Object *obj;
if (ccw) {
return ccw->pv;
}
/* we have to bail out for the "none" machine */
obj = object_dynamic_cast(qdev_get_machine(), TYPE_S390_CCW_MACHINE);
if (!obj) {
return false;
}
ccw = S390_CCW_MACHINE(obj);
return ccw->pv;
}
static bool info_valid;
static struct kvm_s390_pv_info_vm info_vm;
static struct kvm_s390_pv_info_dump info_dump;

24
target/s390x/kvm/pv.h

@ -12,8 +12,6 @@
#ifndef HW_S390_PV_H
#define HW_S390_PV_H
#include "qapi/error.h"
#include "system/kvm.h"
#include "hw/s390x/s390-virtio-ccw.h"
struct S390PVResponse {
@ -23,27 +21,7 @@ struct S390PVResponse {
};
#ifdef CONFIG_KVM
#include "cpu.h"
static inline bool s390_is_pv(void)
{
static S390CcwMachineState *ccw;
Object *obj;
if (ccw) {
return ccw->pv;
}
/* we have to bail out for the "none" machine */
obj = object_dynamic_cast(qdev_get_machine(),
TYPE_S390_CCW_MACHINE);
if (!obj) {
return false;
}
ccw = S390_CCW_MACHINE(obj);
return ccw->pv;
}
bool s390_is_pv(void);
int s390_pv_query_info(void);
int s390_pv_vm_enable(void);
void s390_pv_vm_disable(void);

4
target/s390x/machine.c

@ -52,6 +52,10 @@ static int cpu_pre_save(void *opaque)
kvm_s390_vcpu_interrupt_pre_save(cpu);
}
if (tcg_enabled()) {
tcg_s390_tod_updated(CPU(cpu), RUN_ON_CPU_NULL);
}
return 0;
}

2
target/s390x/s390x-internal.h

@ -259,7 +259,6 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
/* excp_helper.c */
void s390x_cpu_debug_excp_handler(CPUState *cs);
void s390_cpu_do_interrupt(CPUState *cpu);
bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
@ -317,7 +316,6 @@ void s390_cpu_gdb_init(CPUState *cs);
void s390_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
void do_restart_interrupt(CPUS390XState *env);
#ifndef CONFIG_USER_ONLY
void s390_cpu_recompute_watchpoints(CPUState *cs);
void s390x_tod_timer(void *opaque);
void s390x_cpu_timer(void *opaque);
void s390_handle_wait(S390CPU *cpu);

85
target/s390x/tcg/debug.c

@ -0,0 +1,85 @@
/*
* QEMU S/390 debug routines
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "exec/breakpoint.h"
#include "exec/watchpoint.h"
#include "target/s390x/cpu.h"
#include "target/s390x/s390x-internal.h"
#include "tcg_s390x.h"
void s390_cpu_recompute_watchpoints(CPUState *cs)
{
const int wp_flags = BP_CPU | BP_MEM_WRITE | BP_STOP_BEFORE_ACCESS;
CPUS390XState *env = cpu_env(cs);
/* We are called when the watchpoints have changed. First
remove them all. */
cpu_watchpoint_remove_all(cs, BP_CPU);
/* Return if PER is not enabled */
if (!(env->psw.mask & PSW_MASK_PER)) {
return;
}
/* Return if storage-alteration event is not enabled. */
if (!(env->cregs[9] & PER_CR9_EVENT_STORE)) {
return;
}
if (env->cregs[10] == 0 && env->cregs[11] == -1LL) {
/* We can't create a watchoint spanning the whole memory range, so
split it in two parts. */
cpu_watchpoint_insert(cs, 0, 1ULL << 63, wp_flags, NULL);
cpu_watchpoint_insert(cs, 1ULL << 63, 1ULL << 63, wp_flags, NULL);
} else if (env->cregs[10] > env->cregs[11]) {
/* The address range loops, create two watchpoints. */
cpu_watchpoint_insert(cs, env->cregs[10], -env->cregs[10],
wp_flags, NULL);
cpu_watchpoint_insert(cs, 0, env->cregs[11] + 1, wp_flags, NULL);
} else {
/* Default case, create a single watchpoint. */
cpu_watchpoint_insert(cs, env->cregs[10],
env->cregs[11] - env->cregs[10] + 1,
wp_flags, NULL);
}
}
void s390x_cpu_debug_excp_handler(CPUState *cs)
{
CPUS390XState *env = cpu_env(cs);
CPUWatchpoint *wp_hit = cs->watchpoint_hit;
if (wp_hit && wp_hit->flags & BP_CPU) {
/*
* FIXME: When the storage-alteration-space control bit is set,
* the exception should only be triggered if the memory access
* is done using an address space with the storage-alteration-event
* bit set. We have no way to detect that with the current
* watchpoint code.
*/
cs->watchpoint_hit = NULL;
env->per_address = env->psw.addr;
env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env);
/*
* FIXME: We currently no way to detect the address space used
* to trigger the watchpoint. For now just consider it is the
* current default ASC. This turn to be true except when MVCP
* and MVCS instructions are not used.
*/
env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
/*
* Remove all watchpoints to re-execute the code. A PER exception
* will be triggered, it will call s390_cpu_set_psw which will
* recompute the watchpoints.
*/
cpu_watchpoint_remove_all(cs, BP_CPU);
cpu_loop_exit_noexc(cs);
}
}

32
target/s390x/tcg/excp_helper.c

@ -24,7 +24,6 @@
#include "exec/helper-proto.h"
#include "exec/cputlb.h"
#include "exec/target_page.h"
#include "exec/watchpoint.h"
#include "s390x-internal.h"
#include "tcg_s390x.h"
#ifndef CONFIG_USER_ONLY
@ -607,37 +606,6 @@ bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
return false;
}
void s390x_cpu_debug_excp_handler(CPUState *cs)
{
CPUS390XState *env = cpu_env(cs);
CPUWatchpoint *wp_hit = cs->watchpoint_hit;
if (wp_hit && wp_hit->flags & BP_CPU) {
/* FIXME: When the storage-alteration-space control bit is set,
the exception should only be triggered if the memory access
is done using an address space with the storage-alteration-event
bit set. We have no way to detect that with the current
watchpoint code. */
cs->watchpoint_hit = NULL;
env->per_address = env->psw.addr;
env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env);
/* FIXME: We currently no way to detect the address space used
to trigger the watchpoint. For now just consider it is the
current default ASC. This turn to be true except when MVCP
and MVCS instrutions are not used. */
env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
/*
* Remove all watchpoints to re-execute the code. A PER exception
* will be triggered, it will call s390_cpu_set_psw which will
* recompute the watchpoints.
*/
cpu_watchpoint_remove_all(cs, BP_CPU);
cpu_loop_exit_noexc(cs);
}
}
void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr)

3
target/s390x/tcg/meson.build

@ -12,3 +12,6 @@ s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
'vec_int_helper.c',
'vec_string_helper.c',
))
s390x_system_ss.add(when: 'CONFIG_TCG', if_true: files(
'debug.c',
))

5
target/s390x/tcg/tcg_s390x.h

@ -21,4 +21,9 @@ G_NORETURN void tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
G_NORETURN void tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc,
uintptr_t ra);
#ifndef CONFIG_USER_ONLY
void s390_cpu_recompute_watchpoints(CPUState *cs);
void s390x_cpu_debug_excp_handler(CPUState *cs);
#endif
#endif /* TCG_S390X_H */

5
target/s390x/tcg/translate.c

@ -6405,10 +6405,9 @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op, 0);
}
static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
uint64_t pc)
static vaddr get_next_pc(CPUS390XState *env, DisasContext *s, vaddr pc)
{
uint64_t insn = translator_lduw_end(env, &s->base, pc, MO_BE);
uint16_t insn = translator_lduw_end(env, &s->base, pc, MO_BE);
return pc + get_ilen((insn >> 8) & 0xff);
}

1
tests/functional/aarch64/test_smmu.py

@ -50,6 +50,7 @@ class SMMU(LinuxKernelTest):
elif kvm_available(self.qemu_bin):
accel = "kvm"
else:
accel = None # for keeping pylint happy
self.skipTest("Neither HVF nor KVM accelerator is available")
self.require_accelerator(accel)
self.require_netdev('user')

20
tests/functional/aarch64/test_virt_gpu.py

@ -9,16 +9,16 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu.machine.machine import VMLaunchFailure
from re import search
from subprocess import check_output, CalledProcessError
from qemu_test import Asset
from qemu_test import Asset, skipIfMissingCommands
from qemu_test import exec_command_and_wait_for_pattern as ec_and_wait
from qemu_test import skipIfMissingCommands
from qemu_test.linuxkernel import LinuxKernelTest
from re import search
from subprocess import check_output, CalledProcessError
from qemu.machine.machine import VMLaunchFailure
class Aarch64VirtGPUMachine(LinuxKernelTest):
@ -81,16 +81,16 @@ class Aarch64VirtGPUMachine(LinuxKernelTest):
self.wait_for_console_pattern('buildroot login:')
ec_and_wait(self, 'root', '#')
def _run_virt_weston_test(self, cmd, fail = None):
def _run_virt_weston_test(self, cmd, fail=None):
# make it easier to detect successful return to shell
PS1 = 'RES=[$?] # '
OK_CMD = 'RES=[0] # '
ps1 = 'RES=[$?] # '
ok_cmd = 'RES=[0] # '
ec_and_wait(self, 'export XDG_RUNTIME_DIR=/tmp', '#')
ec_and_wait(self, f"export PS1='{PS1}'", OK_CMD)
ec_and_wait(self, f"export PS1='{ps1}'", ok_cmd)
full_cmd = f"weston -B headless --renderer gl --shell kiosk -- {cmd}"
ec_and_wait(self, full_cmd, OK_CMD, fail)
ec_and_wait(self, full_cmd, ok_cmd, fail)
@skipIfMissingCommands('zstd')
def test_aarch64_virt_with_virgl_gpu(self):

1
tests/functional/generic/meson.build

@ -3,6 +3,7 @@
tests_generic_system = [
'empty_cpu_model',
'info_usernet',
'linters',
'version',
'vnc',
]

41
tests/functional/generic/test_linters.py

@ -0,0 +1,41 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
'''Python linter tests'''
import os
from pathlib import Path
from qemu_test import QemuBaseTest, skipIfMissingImports
class LinterTest(QemuBaseTest):
'''
Run python linters on the test *.py files
'''
@skipIfMissingImports("pylint")
def test_pylint(self):
'''Check source files with pylint'''
from pylint.lint import Run as pylint_run
from pylint.reporters.collecting_reporter import CollectingReporter
srcdir = os.path.join(Path(__file__).parent.parent, self.arch)
rcfile = os.path.join(Path(__file__).parent.parent, "pylintrc")
self.log.info('Checking files in %s with pylint', srcdir)
reporter = CollectingReporter()
pylint_run(["--rcfile", rcfile, srcdir], reporter=reporter, exit=False)
if reporter.messages:
fmt = '"{path}:{line}: {msg_id}: {msg} ({symbol})"'
for msg in reporter.messages:
if msg.category == "error":
self.log.error(msg.format(fmt))
elif msg.category == "warning":
self.log.warning(msg.format(fmt))
else:
self.log.info(msg.format(fmt))
self.fail("Pylint failed, see base.log for details.")
if __name__ == '__main__':
QemuBaseTest.main()

8
tests/functional/mips/test_malta.py

@ -50,7 +50,7 @@ def mips_run_common_commands(test, prompt='#'):
' : ata_piix')
wait_for_console_pattern(test, prompt)
def mips_check_wheezy(test, kernel_path, image_path, kernel_command_line,
def mips_check_wheezy(test, kernel_path, image_path, kernel_command_line, *,
dl_file, hsum, nic='pcnet', cpuinfo='MIPS 24Kc'):
test.require_netdev('user')
test.require_device(nic)
@ -59,10 +59,10 @@ def mips_check_wheezy(test, kernel_path, image_path, kernel_command_line,
port=8080
test.vm.add_args('-kernel', kernel_path,
'-append', kernel_command_line,
'-drive', 'file=%s,snapshot=on' % image_path,
'-drive', f'file={image_path},snapshot=on',
'-netdev', 'user,id=n1' +
',tftp=' + os.path.basename(kernel_path) +
',hostfwd=tcp:127.0.0.1:0-:%d' % port,
f',hostfwd=tcp:127.0.0.1:0-:{port}',
'-device', f'{nic},netdev=n1',
'-no-reboot')
test.vm.set_console()
@ -111,7 +111,7 @@ class MaltaMachineConsole(LinuxKernelTest):
self.vm.add_args('-kernel', kernel_path,
'-append', kernel_command_line)
self.vm.launch()
console_pattern = 'Kernel command line: %s' % kernel_command_line
console_pattern = f'Kernel command line: {kernel_command_line}'
self.wait_for_console_pattern(console_pattern)
ASSET_KERNEL_4_5_0 = Asset(

10
tests/functional/ppc64/test_hv.py

@ -29,8 +29,6 @@ from qemu_test import exec_command_and_wait_for_pattern
@skipBigDataTest()
class HypervisorTest(QemuSystemTest):
timeout = 1000
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '
panic_message = 'Kernel panic - not syncing'
good_message = 'VFS: Cannot open root device'
@ -49,8 +47,8 @@ class HypervisorTest(QemuSystemTest):
"""
filename = self.scratch_file(os.path.basename(path))
cmd = "xorriso -osirrox on -indev %s -cpx %s %s" % (iso, path, filename)
subprocess.run(cmd.split(),
cmd = f"xorriso -osirrox on -indev {iso} -cpx {path} {filename}"
subprocess.run(cmd.split(), check=True,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
os.chmod(filename, 0o600)
@ -66,7 +64,6 @@ class HypervisorTest(QemuSystemTest):
def do_start_alpine(self):
self.vm.set_console()
kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE
self.vm.add_args("-kernel", self.vmlinuz)
self.vm.add_args("-initrd", self.initramfs)
self.vm.add_args("-smp", "4", "-m", "2g")
@ -78,7 +75,8 @@ class HypervisorTest(QemuSystemTest):
wait_for_console_pattern(self, 'localhost login:')
exec_command_and_wait_for_pattern(self, 'root', ps1)
# If the time is wrong, SSL certificates can fail.
exec_command_and_wait_for_pattern(self, 'date -s "' + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S' + '"'), ps1)
cmd='date -s "' + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S' + '"')
exec_command_and_wait_for_pattern(self, cmd, ps1)
ps1='alpine:~#'
exec_command_and_wait_for_pattern(self, 'setup-alpine -qe', ps1)
exec_command_and_wait_for_pattern(self, 'setup-apkrepos -c1', ps1)

84
tests/functional/pylintrc

@ -0,0 +1,84 @@
# Config file for checking the functional tests with pylint
#
# SPDX-License-Identifier: GPL-2.0-or-later
[DESIGN]
# Maximum number of arguments for function / method.
max-args=9
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=12
# Maximum number of locals for function / method body.
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of positional arguments for function / method.
max-positional-arguments=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
# UNDEFINED.
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=bad-inline-option,
consider-using-f-string,
file-ignored,
fixme,
import-outside-toplevel,
locally-disabled,
logging-fstring-interpolation,
logging-not-lazy,
missing-function-docstring,
missing-module-docstring,
missing-class-docstring,
raw-checker-failed,
suppressed-message,
too-many-locals,
too-many-statements,
use-implicit-booleaness-not-comparison-to-string,
use-implicit-booleaness-not-comparison-to-zero,
use-symbolic-message-instead,
useless-suppression,
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=20

4
tests/functional/reverse_debugging.py

@ -64,7 +64,7 @@ class ReverseDebugging(LinuxKernelTest):
@skipIfMissingImports("pygdbmi") # Required by GDB class
@skipIfMissingEnv("QEMU_TEST_GDB")
def reverse_debugging(self, gdb_arch, shift=7, args=None):
def reverse_debugging(self, gdb_arch, shift=7, args=None, big_endian=False):
from qemu_test import GDB
# create qcow2 for snapshots
@ -99,6 +99,8 @@ class ReverseDebugging(LinuxKernelTest):
gdb_cmd = os.getenv('QEMU_TEST_GDB')
gdb = GDB(gdb_cmd)
try:
if big_endian:
gdb.cli("set endian big")
self.reverse_debugging_run(gdb, vm, port, gdb_arch, last_icount)
finally:
self.log.info('exiting gdb and qemu')

1
tests/functional/s390x/meson.build

@ -6,6 +6,7 @@ test_s390x_timeouts = {
tests_s390x_system_quick = [
'vmstate',
'reverse_debug',
]
tests_s390x_system_thorough = [

21
tests/functional/s390x/test_reverse_debug.py

@ -0,0 +1,21 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
'''
Reverse debugging test for s390x
'''
from reverse_debugging import ReverseDebugging
class ReverseDebuggingS390x(ReverseDebugging):
def test_revdbg(self):
self.set_machine('s390-ccw-virtio')
self.reverse_debugging(gdb_arch='s390:64-bit', shift=6,
big_endian=True, args=('-no-shutdown',))
if __name__ == '__main__':
ReverseDebugging.main()

30
util/qemu-timer.c

@ -30,6 +30,7 @@
#include "exec/icount.h"
#include "system/replay.h"
#include "system/cpus.h"
#include "hw/core/cpu.h"
#ifdef CONFIG_POSIX
#include <pthread.h>
@ -387,11 +388,40 @@ static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts)
}
}
static void timer_fire(CPUState *cpu, run_on_cpu_data data)
{
QEMUTimer *t = data.host_ptr;
t->cb(t->opaque);
}
static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
QEMUTimer *ts, int64_t expire_time)
{
QEMUTimer **pt, *t;
/*
* Normally during record-replay virtual clock timers and CPU work are
* deterministically ordered. This is because the virtual clock can be
* advanced only by instructions running on a CPU.
*
* A notable exception are timers that are armed already expired. Their
* expiration is not constrained by instruction execution, and, therefore,
* their ordering relative to CPU work is affected by what the
* record-replay thread is doing when they are armed. This introduces
* non-determinism.
*
* Convert such timers to CPU work in order to avoid it.
*/
if (replay_mode != REPLAY_MODE_NONE &&
timer_list->clock->type == QEMU_CLOCK_VIRTUAL &&
!(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL) &&
expire_time <= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) {
async_run_on_cpu(first_cpu, timer_fire,
RUN_ON_CPU_HOST_PTR(ts));
return false;
}
/* add the timer in the sorted list */
pt = &timer_list->active_timers;
for (;;) {

Loading…
Cancel
Save