From 314a31ea0ba06160a54972ecf08ae56bc0c6b094 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 6 Oct 2025 19:03:04 +0200 Subject: [PATCH 1/9] tests/functional: Drop the "Attempting to cache ..." log text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fetch() function already either prints "Using cached asset ..." or "Downloading ... to ..." with the same file name to the log, so the "Attempting to cache ..." message does not provide any additional valuable information. Thus let's drop it to limit the length of the logging output to a more reasonable size. Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth Message-ID: <20251006170304.197387-1-thuth@redhat.com> --- tests/functional/qemu_test/asset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index 2971a989d1..f666125bfa 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -225,7 +225,6 @@ class Asset: log.addHandler(handler) for name, asset in vars(test.__class__).items(): if name.startswith("ASSET_") and type(asset) == Asset: - log.info("Attempting to cache '%s'" % asset) try: asset.fetch() except AssetError as e: From 8dd912b042f47bb0468f097df708cf2fab2af614 Mon Sep 17 00:00:00 2001 From: Jaehoon Kim Date: Wed, 1 Oct 2025 10:39:38 -0500 Subject: [PATCH 2/9] s390x/pci: fix interrupt blocking by returning only the device's summary bit Previously, set_ind_atomic() returned the entire byte containing multiple summary bits. This meant that if any other summary bit in the byte was set, interrupt injection could be incorrectly blocked, even when the current device's summary bit was not set. As a result, the guest could remain blocked after I/O completion during FIO tests. This patch replaces set_ind_atomic() with set_ind_bit_atomic(), which returns true if the bit was set by this function, and false if it was already set or mapping failed. Interrupts are now blocked only when the device's own summary bit was not previously set, avoiding unintended blocking when multiple PCI summary bits exist within the same byte. Signed-off-by: Jaehoon Kim Reviewed-by: Halil Pasic Reviewed-by: Eric Farman Reviewed-by: Christian Borntraeger Reviewed-by: Matthew Rosato Message-ID: <20251001154004.71917-1-jhkim@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-bus.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index f87d2748b6..e8e41c8a9a 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -652,7 +652,16 @@ static const PCIIOMMUOps s390_iommu_ops = { .get_address_space = s390_pci_dma_iommu, }; -static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) +/** + * set_ind_bit_atomic - Atomically set a bit in an indicator + * + * @ind_loc: Address of the indicator + * @to_be_set: Bit to set + * + * Returns true if the bit was set by this function, false if it was + * already set or mapping failed. + */ +static bool set_ind_bit_atomic(uint64_t ind_loc, uint8_t to_be_set) { uint8_t expected, actual; hwaddr len = 1; @@ -662,7 +671,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) ind_addr = cpu_physical_memory_map(ind_loc, &len, true); if (!ind_addr) { s390_pci_generate_error_event(ERR_EVENT_AIRERR, 0, 0, 0, 0); - return -1; + return false; } actual = *ind_addr; do { @@ -671,7 +680,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) } while (actual != expected); cpu_physical_memory_unmap((void *)ind_addr, len, 1, len); - return actual; + return (actual & to_be_set) ? false : true; } static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, @@ -693,10 +702,10 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, ind_bit = pbdev->routes.adapter.ind_offset; sum_bit = pbdev->routes.adapter.summary_offset; - set_ind_atomic(pbdev->routes.adapter.ind_addr + (ind_bit + vec) / 8, + set_ind_bit_atomic(pbdev->routes.adapter.ind_addr + (ind_bit + vec) / 8, 0x80 >> ((ind_bit + vec) % 8)); - if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8, - 0x80 >> (sum_bit % 8))) { + if (set_ind_bit_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8, + 0x80 >> (sum_bit % 8))) { css_adapter_interrupt(CSS_IO_ADAPTER_PCI, pbdev->isc); } } From d24ac20c6a86b32d64b90a90693c97086eba0f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 2 Oct 2025 11:11:27 +0200 Subject: [PATCH 3/9] target/s390x: Replace legacy cpu_physical_memory_[un]map() calls (1/3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b7ecba0f6f6 ("docs/devel/loads-stores.rst: Document our various load and store APIs") mentioned cpu_physical_memory_*() methods are legacy, the replacement being address_space_*(). Replace the *_map() / *_unmap() methods in mchk_store_vregs(). No behavioral change expected. Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20251002091132.65703-5-philmd@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/tcg/excp_helper.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c index 4c7faeee82..5e1d4dc958 100644 --- a/target/s390x/tcg/excp_helper.c +++ b/target/s390x/tcg/excp_helper.c @@ -30,6 +30,7 @@ #ifndef CONFIG_USER_ONLY #include "qemu/timer.h" #include "system/address-spaces.h" +#include "system/memory.h" #include "hw/s390x/ioinst.h" #include "hw/s390x/s390_flic.h" #include "hw/boards.h" @@ -418,16 +419,18 @@ QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024); static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + AddressSpace *as = env_cpu(env)->as; hwaddr len = sizeof(MchkExtSaveArea); MchkExtSaveArea *sa; int i; - sa = cpu_physical_memory_map(mcesao, &len, true); + sa = address_space_map(as, mcesao, &len, true, attrs); if (!sa) { return -EFAULT; } if (len != sizeof(MchkExtSaveArea)) { - cpu_physical_memory_unmap(sa, len, 1, 0); + address_space_unmap(as, sa, len, true, 0); return -EFAULT; } @@ -436,7 +439,7 @@ static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao) sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1]); } - cpu_physical_memory_unmap(sa, len, 1, len); + address_space_unmap(as, sa, len, true, len); return 0; } From c35b166c1dc2d0332d2199ea8f36cf4eaa9eda35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 2 Oct 2025 11:11:28 +0200 Subject: [PATCH 4/9] target/s390x: Propagate CPUS390XState to cpu_unmap_lowcore() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be able to access the CPU state in cpu_unmap_lowcore() in the next commit, propagate it as argument. cpu_map_lowcore() already takes it. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-ID: <20251002091132.65703-6-philmd@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/helper.c | 4 ++-- target/s390x/s390x-internal.h | 2 +- target/s390x/tcg/excp_helper.c | 10 +++++----- target/s390x/tcg/misc_helper.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 5c127da1a6..a6d4a1ce05 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -117,7 +117,7 @@ LowCore *cpu_map_lowcore(CPUS390XState *env) return lowcore; } -void cpu_unmap_lowcore(LowCore *lowcore) +void cpu_unmap_lowcore(CPUS390XState *env, LowCore *lowcore) { cpu_physical_memory_unmap(lowcore, sizeof(LowCore), 1, sizeof(LowCore)); } @@ -134,7 +134,7 @@ void do_restart_interrupt(CPUS390XState *env) mask = be64_to_cpu(lowcore->restart_new_psw.mask); addr = be64_to_cpu(lowcore->restart_new_psw.addr); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); env->pending_int &= ~INTERRUPT_RESTART; s390_cpu_set_psw(env, mask, addr); diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h index 56cce2e7f5..1fb752aa1d 100644 --- a/target/s390x/s390x-internal.h +++ b/target/s390x/s390x-internal.h @@ -327,7 +327,7 @@ hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch); int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len); LowCore *cpu_map_lowcore(CPUS390XState *env); -void cpu_unmap_lowcore(LowCore *lowcore); +void cpu_unmap_lowcore(CPUS390XState *env, LowCore *lowcore); #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c index 5e1d4dc958..0ae4e26606 100644 --- a/target/s390x/tcg/excp_helper.c +++ b/target/s390x/tcg/excp_helper.c @@ -285,7 +285,7 @@ static void do_program_interrupt(CPUS390XState *env) addr = be64_to_cpu(lowcore->program_new_psw.addr); lowcore->per_breaking_event_addr = cpu_to_be64(env->gbea); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); s390_cpu_set_psw(env, mask, addr); } @@ -304,7 +304,7 @@ static void do_svc_interrupt(CPUS390XState *env) mask = be64_to_cpu(lowcore->svc_new_psw.mask); addr = be64_to_cpu(lowcore->svc_new_psw.addr); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); s390_cpu_set_psw(env, mask, addr); @@ -378,7 +378,7 @@ static void do_ext_interrupt(CPUS390XState *env) lowcore->external_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env)); lowcore->external_old_psw.addr = cpu_to_be64(env->psw.addr); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); s390_cpu_set_psw(env, mask, addr); } @@ -405,7 +405,7 @@ static void do_io_interrupt(CPUS390XState *env) mask = be64_to_cpu(lowcore->io_new_psw.mask); addr = be64_to_cpu(lowcore->io_new_psw.addr); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); g_free(io); s390_cpu_set_psw(env, mask, addr); @@ -491,7 +491,7 @@ static void do_mchk_interrupt(CPUS390XState *env) mask = be64_to_cpu(lowcore->mcck_new_psw.mask); addr = be64_to_cpu(lowcore->mcck_new_psw.addr); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); s390_cpu_set_psw(env, mask, addr); } diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c index f7101be574..6d9d601d29 100644 --- a/target/s390x/tcg/misc_helper.c +++ b/target/s390x/tcg/misc_helper.c @@ -570,7 +570,7 @@ uint32_t HELPER(tpi)(CPUS390XState *env, uint64_t addr) lowcore->subchannel_nr = cpu_to_be16(io->nr); lowcore->io_int_parm = cpu_to_be32(io->parm); lowcore->io_int_word = cpu_to_be32(io->word); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); } g_free(io); @@ -700,7 +700,7 @@ void HELPER(stfl)(CPUS390XState *env) lowcore = cpu_map_lowcore(env); prepare_stfl(); memcpy(&lowcore->stfl_fac_list, stfl_bytes, sizeof(lowcore->stfl_fac_list)); - cpu_unmap_lowcore(lowcore); + cpu_unmap_lowcore(env, lowcore); } #endif From 64321858d0735191b6160ba78f2282a67df6d9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 2 Oct 2025 11:11:29 +0200 Subject: [PATCH 5/9] target/s390x: Replace legacy cpu_physical_memory_[un]map() calls (2/3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b7ecba0f6f6 ("docs/devel/loads-stores.rst: Document our various load and store APIs") mentioned cpu_physical_memory_*() methods are legacy, the replacement being address_space_*(). Replace the *_map() / *_unmap() methods in cpu_[un]map_lowcore(). No behavioral change expected. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-ID: <20251002091132.65703-7-philmd@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/helper.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index a6d4a1ce05..b01b7d9bbb 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -26,6 +26,7 @@ #include "hw/s390x/ioinst.h" #include "target/s390x/kvm/pv.h" #include "system/hw_accel.h" +#include "system/memory.h" #include "system/runstate.h" #include "exec/target_page.h" #include "exec/watchpoint.h" @@ -107,11 +108,13 @@ LowCore *cpu_map_lowcore(CPUS390XState *env) { LowCore *lowcore; hwaddr len = sizeof(LowCore); + CPUState *cs = env_cpu(env); + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; - lowcore = cpu_physical_memory_map(env->psa, &len, true); + lowcore = address_space_map(cs->as, env->psa, &len, true, attrs); if (len < sizeof(LowCore)) { - cpu_abort(env_cpu(env), "Could not map lowcore\n"); + cpu_abort(cs, "Could not map lowcore\n"); } return lowcore; @@ -119,7 +122,9 @@ LowCore *cpu_map_lowcore(CPUS390XState *env) void cpu_unmap_lowcore(CPUS390XState *env, LowCore *lowcore) { - cpu_physical_memory_unmap(lowcore, sizeof(LowCore), 1, sizeof(LowCore)); + AddressSpace *as = env_cpu(env)->as; + + address_space_unmap(as, lowcore, sizeof(LowCore), true, sizeof(LowCore)); } void do_restart_interrupt(CPUS390XState *env) From 1819902285177c8781ab4ef92cc44e0882c0dec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 2 Oct 2025 11:11:30 +0200 Subject: [PATCH 6/9] target/s390x: Reduce s390_store_adtl_status() scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s390_store_adtl_status() is only called within sigp.c, move it and the SigpAdtlSaveArea structure definition there where it belongs, with other SIGP handling code. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-ID: <20251002091132.65703-8-philmd@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/helper.c | 40 ----------------------------------- target/s390x/s390x-internal.h | 1 - target/s390x/sigp.c | 40 +++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index b01b7d9bbb..84321e1d68 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -248,43 +248,3 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) return 0; } - -typedef struct SigpAdtlSaveArea { - uint64_t vregs[32][2]; /* 0x0000 */ - uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */ - uint64_t gscb[4]; /* 0x0400 */ - uint8_t pad_0x0420[0x1000 - 0x0420]; /* 0x0420 */ -} SigpAdtlSaveArea; -QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096); - -#define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */ -int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) -{ - SigpAdtlSaveArea *sa; - hwaddr save = len; - int i; - - sa = cpu_physical_memory_map(addr, &save, true); - if (!sa) { - return -EFAULT; - } - if (save != len) { - cpu_physical_memory_unmap(sa, len, 1, 0); - return -EFAULT; - } - - if (s390_has_feat(S390_FEAT_VECTOR)) { - for (i = 0; i < 32; i++) { - sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0]); - sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1]); - } - } - if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) { - for (i = 0; i < 4; i++) { - sa->gscb[i] = cpu_to_be64(cpu->env.gscb[i]); - } - } - - cpu_physical_memory_unmap(sa, len, 1, len); - return 0; -} diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h index 1fb752aa1d..a49dca94a7 100644 --- a/target/s390x/s390x-internal.h +++ b/target/s390x/s390x-internal.h @@ -325,7 +325,6 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); #define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch); -int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len); LowCore *cpu_map_lowcore(CPUS390XState *env); void cpu_unmap_lowcore(CPUS390XState *env, LowCore *lowcore); #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c index 5e95c4978f..1464be7698 100644 --- a/target/s390x/sigp.c +++ b/target/s390x/sigp.c @@ -172,6 +172,46 @@ static void sigp_store_status_at_address(CPUState *cs, run_on_cpu_data arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +typedef struct SigpAdtlSaveArea { + uint64_t vregs[32][2]; /* 0x0000 */ + uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */ + uint64_t gscb[4]; /* 0x0400 */ + uint8_t pad_0x0420[0x1000 - 0x0420]; /* 0x0420 */ +} SigpAdtlSaveArea; +QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096); + +#define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */ +static int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) +{ + SigpAdtlSaveArea *sa; + hwaddr save = len; + int i; + + sa = cpu_physical_memory_map(addr, &save, true); + if (!sa) { + return -EFAULT; + } + if (save != len) { + cpu_physical_memory_unmap(sa, len, 1, 0); + return -EFAULT; + } + + if (s390_has_feat(S390_FEAT_VECTOR)) { + for (i = 0; i < 32; i++) { + sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0]); + sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1]); + } + } + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) { + for (i = 0; i < 4; i++) { + sa->gscb[i] = cpu_to_be64(cpu->env.gscb[i]); + } + } + + cpu_physical_memory_unmap(sa, len, 1, len); + return 0; +} + #define ADTL_SAVE_LC_MASK 0xfUL static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg) { From db7721857b3033222a521acc2ace7d3ed9529cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 2 Oct 2025 11:11:31 +0200 Subject: [PATCH 7/9] target/s390x: Reduce s390_store_status() scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s390_store_status() is only called within sigp.c, move it and the SigpSaveArea structure definition there where it belongs, with other SIGP handling code. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-ID: <20251002091132.65703-9-philmd@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/helper.c | 67 ---------------------------------- target/s390x/s390x-internal.h | 2 -- target/s390x/sigp.c | 68 +++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 69 deletions(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 84321e1d68..184428c6d9 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -24,7 +24,6 @@ #include "gdbstub/helpers.h" #include "qemu/timer.h" #include "hw/s390x/ioinst.h" -#include "target/s390x/kvm/pv.h" #include "system/hw_accel.h" #include "system/memory.h" #include "system/runstate.h" @@ -182,69 +181,3 @@ void s390_cpu_recompute_watchpoints(CPUState *cs) wp_flags, NULL); } } - -typedef struct SigpSaveArea { - uint64_t fprs[16]; /* 0x0000 */ - uint64_t grs[16]; /* 0x0080 */ - PSW psw; /* 0x0100 */ - uint8_t pad_0x0110[0x0118 - 0x0110]; /* 0x0110 */ - uint32_t prefix; /* 0x0118 */ - uint32_t fpc; /* 0x011c */ - uint8_t pad_0x0120[0x0124 - 0x0120]; /* 0x0120 */ - uint32_t todpr; /* 0x0124 */ - uint64_t cputm; /* 0x0128 */ - uint64_t ckc; /* 0x0130 */ - uint8_t pad_0x0138[0x0140 - 0x0138]; /* 0x0138 */ - uint32_t ars[16]; /* 0x0140 */ - uint64_t crs[16]; /* 0x0384 */ -} SigpSaveArea; -QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512); - -int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) -{ - static const uint8_t ar_id = 1; - SigpSaveArea *sa; - hwaddr len = sizeof(*sa); - int i; - - /* For PVMs storing will occur when this cpu enters SIE again */ - if (s390_is_pv()) { - return 0; - } - - sa = cpu_physical_memory_map(addr, &len, true); - if (!sa) { - return -EFAULT; - } - if (len != sizeof(*sa)) { - cpu_physical_memory_unmap(sa, len, 1, 0); - return -EFAULT; - } - - if (store_arch) { - cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1); - } - for (i = 0; i < 16; ++i) { - sa->fprs[i] = cpu_to_be64(*get_freg(&cpu->env, i)); - } - for (i = 0; i < 16; ++i) { - sa->grs[i] = cpu_to_be64(cpu->env.regs[i]); - } - sa->psw.addr = cpu_to_be64(cpu->env.psw.addr); - sa->psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(&cpu->env)); - sa->prefix = cpu_to_be32(cpu->env.psa); - sa->fpc = cpu_to_be32(cpu->env.fpc); - sa->todpr = cpu_to_be32(cpu->env.todpr); - sa->cputm = cpu_to_be64(cpu->env.cputm); - sa->ckc = cpu_to_be64(cpu->env.ckc >> 8); - for (i = 0; i < 16; ++i) { - sa->ars[i] = cpu_to_be32(cpu->env.aregs[i]); - } - for (i = 0; i < 16; ++i) { - sa->crs[i] = cpu_to_be64(cpu->env.cregs[i]); - } - - cpu_physical_memory_unmap(sa, len, 1, len); - - return 0; -} diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h index a49dca94a7..9691366ec9 100644 --- a/target/s390x/s390x-internal.h +++ b/target/s390x/s390x-internal.h @@ -323,8 +323,6 @@ void s390x_cpu_timer(void *opaque); void s390_handle_wait(S390CPU *cpu); hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); -#define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) -int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch); LowCore *cpu_map_lowcore(CPUS390XState *env); void cpu_unmap_lowcore(CPUS390XState *env, LowCore *lowcore); #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c index 1464be7698..2487acdb49 100644 --- a/target/s390x/sigp.c +++ b/target/s390x/sigp.c @@ -19,6 +19,7 @@ #include "system/tcg.h" #include "trace.h" #include "qapi/qapi-types-machine.h" +#include "target/s390x/kvm/pv.h" QemuMutex qemu_sigp_mutex; @@ -126,6 +127,73 @@ static void sigp_stop(CPUState *cs, run_on_cpu_data arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +typedef struct SigpSaveArea { + uint64_t fprs[16]; /* 0x0000 */ + uint64_t grs[16]; /* 0x0080 */ + PSW psw; /* 0x0100 */ + uint8_t pad_0x0110[0x0118 - 0x0110]; /* 0x0110 */ + uint32_t prefix; /* 0x0118 */ + uint32_t fpc; /* 0x011c */ + uint8_t pad_0x0120[0x0124 - 0x0120]; /* 0x0120 */ + uint32_t todpr; /* 0x0124 */ + uint64_t cputm; /* 0x0128 */ + uint64_t ckc; /* 0x0130 */ + uint8_t pad_0x0138[0x0140 - 0x0138]; /* 0x0138 */ + uint32_t ars[16]; /* 0x0140 */ + uint64_t crs[16]; /* 0x0384 */ +} SigpSaveArea; +QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512); + +#define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) +static int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) +{ + static const uint8_t ar_id = 1; + SigpSaveArea *sa; + hwaddr len = sizeof(*sa); + int i; + + /* For PVMs storing will occur when this cpu enters SIE again */ + if (s390_is_pv()) { + return 0; + } + + sa = cpu_physical_memory_map(addr, &len, true); + if (!sa) { + return -EFAULT; + } + if (len != sizeof(*sa)) { + cpu_physical_memory_unmap(sa, len, 1, 0); + return -EFAULT; + } + + if (store_arch) { + cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1); + } + for (i = 0; i < 16; ++i) { + sa->fprs[i] = cpu_to_be64(*get_freg(&cpu->env, i)); + } + for (i = 0; i < 16; ++i) { + sa->grs[i] = cpu_to_be64(cpu->env.regs[i]); + } + sa->psw.addr = cpu_to_be64(cpu->env.psw.addr); + sa->psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(&cpu->env)); + sa->prefix = cpu_to_be32(cpu->env.psa); + sa->fpc = cpu_to_be32(cpu->env.fpc); + sa->todpr = cpu_to_be32(cpu->env.todpr); + sa->cputm = cpu_to_be64(cpu->env.cputm); + sa->ckc = cpu_to_be64(cpu->env.ckc >> 8); + for (i = 0; i < 16; ++i) { + sa->ars[i] = cpu_to_be32(cpu->env.aregs[i]); + } + for (i = 0; i < 16; ++i) { + sa->crs[i] = cpu_to_be64(cpu->env.cregs[i]); + } + + cpu_physical_memory_unmap(sa, len, 1, len); + + return 0; +} + static void sigp_stop_and_store_status(CPUState *cs, run_on_cpu_data arg) { S390CPU *cpu = S390_CPU(cs); From 00457aed51a240d6478e0870cd17fdcaa5f6a0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 2 Oct 2025 11:11:32 +0200 Subject: [PATCH 8/9] target/s390x: Replace legacy cpu_physical_memory_[un]map() calls (3/3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b7ecba0f6f6 ("docs/devel/loads-stores.rst: Document our various load and store APIs") mentioned cpu_physical_memory_*() methods are legacy, the replacement being address_space_*(). Replace the *_map() / *_unmap() methods in s390_store_status() and s390_store_adtl_status(). In s390_store_status(), replace cpu_physical_memory_write() by address_space_stb(), restricting @ar_id scope. No behavioral change expected. Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20251002091132.65703-10-philmd@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/sigp.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c index 2487acdb49..f5d7bc0fa2 100644 --- a/target/s390x/sigp.c +++ b/target/s390x/sigp.c @@ -13,6 +13,7 @@ #include "s390x-internal.h" #include "hw/boards.h" #include "system/hw_accel.h" +#include "system/memory.h" #include "system/runstate.h" #include "system/address-spaces.h" #include "exec/cputlb.h" @@ -147,7 +148,8 @@ QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512); #define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) static int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) { - static const uint8_t ar_id = 1; + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + AddressSpace *as = CPU(cpu)->as; SigpSaveArea *sa; hwaddr len = sizeof(*sa); int i; @@ -157,17 +159,21 @@ static int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) return 0; } - sa = cpu_physical_memory_map(addr, &len, true); + sa = address_space_map(as, addr, &len, true, attrs); if (!sa) { return -EFAULT; } if (len != sizeof(*sa)) { - cpu_physical_memory_unmap(sa, len, 1, 0); + address_space_unmap(as, sa, len, true, 0); return -EFAULT; } if (store_arch) { - cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1); + static const uint8_t ar_id = 1; + + address_space_stb(as, offsetof(LowCore, ar_access_id), + ar_id, attrs, NULL); + } for (i = 0; i < 16; ++i) { sa->fprs[i] = cpu_to_be64(*get_freg(&cpu->env, i)); @@ -189,7 +195,7 @@ static int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) sa->crs[i] = cpu_to_be64(cpu->env.cregs[i]); } - cpu_physical_memory_unmap(sa, len, 1, len); + address_space_unmap(as, sa, len, true, len); return 0; } @@ -251,16 +257,18 @@ QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096); #define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */ static int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + AddressSpace *as = CPU(cpu)->as; SigpAdtlSaveArea *sa; hwaddr save = len; int i; - sa = cpu_physical_memory_map(addr, &save, true); + sa = address_space_map(as, addr, &save, true, attrs); if (!sa) { return -EFAULT; } if (save != len) { - cpu_physical_memory_unmap(sa, len, 1, 0); + address_space_unmap(as, sa, len, true, 0); return -EFAULT; } @@ -276,7 +284,8 @@ static int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) } } - cpu_physical_memory_unmap(sa, len, 1, len); + address_space_unmap(as, sa, len, true, len); + return 0; } From 47ea7263701e85ea03270d34c9a90f3971597e06 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Wed, 8 Oct 2025 16:33:50 -0400 Subject: [PATCH 9/9] s390x/pci: set kvm_msi_via_irqfd_allowed Allow irqfd to be used for virtio-pci on s390x if the kernel supports it. This improves s390x virtio-pci performance when using kvm acceleration by allowing kvm to deliver interrupts instead of QEMU. Signed-off-by: Matthew Rosato Reviewed-by: Farhan Ali Reviewed-by: Eric Farman Message-ID: <20251008203350.354121-1-mjrosato@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-bus.c | 1 + include/hw/s390x/s390-pci-kvm.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index e8e41c8a9a..52820894fa 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -900,6 +900,7 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp) s390_pci_init_default_group(); css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, S390_ADAPTER_SUPPRESSIBLE, errp); + s390_pcihost_kvm_realize(); } static void s390_pcihost_unrealize(DeviceState *dev) diff --git a/include/hw/s390x/s390-pci-kvm.h b/include/hw/s390x/s390-pci-kvm.h index 933814a402..c33f2833a3 100644 --- a/include/hw/s390x/s390-pci-kvm.h +++ b/include/hw/s390x/s390-pci-kvm.h @@ -14,12 +14,19 @@ #include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/s390-pci-inst.h" +#include "system/kvm.h" #ifdef CONFIG_KVM +static inline void s390_pcihost_kvm_realize(void) +{ + kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); +} + bool s390_pci_kvm_interp_allowed(void); int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist); int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev); #else +static inline void s390_pcihost_kvm_realize(void) {} static inline bool s390_pci_kvm_interp_allowed(void) { return false;