Merge tag 'pull-target-arm-20230725' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue:
* tests/decode: Suppress "error: " string for expected-failure tests
* ui/curses: For curses display, recognize a few more control keys
* target/arm: Special case M-profile in debug_helper.c code
* scripts/git-submodule.sh: Don't rely on non-POSIX 'read' behaviour
* hw/arm/smmu: Handle big-endian hosts correctly
# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmS/ot8ZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3slqEACaLJwIYl1bJBfCda2u53+C
# q20t50SQjkvV2CSW6A9uOHPPahKUcxAXh6K+d54BhzD6Dsrv5g1rpo/2fnNhHDSG
# 7fHlla+fPnywmAOahE2FPUw4pckRX1tpPIM1RDjM9szLYqkJlShKYP28QsLu1Eku
# bnTty6OcId5hAZILag53QLwL9EYsVYoCEe6xRcgY3He0UZcCEisCUdfeCXEN1Uc8
# 57wd+q3KNUTgOScqmDJRAH2NaET0UOYlUvQGVu8/Bh3t0huQCtfyT4gc8z7v/TZ8
# 2PfI6bFb9nei09avxhBMN9Nu7BVD6eHBkAAe4JHDBhkJKCZn+LASDCMUAFPrFD2V
# NeIObNHBMaE9FqIG/SZxf7kEOaFcUwt4GrVfQNguaqiXIwALsfT/jiX4r+jXX4WS
# ii0mdoS2ZuAcRtUhTA7S6x44B3wa47sidSogoe3t2k8ObYB/AZ34F1cSZDgEmIG7
# nobJE2OgzSRMWUHXhCUEzGvn8MMPeI0HQmKr4sOD6CnlqHIzLZDH4Jx0DL4yvoyc
# XLs0D2G4yscUTtWh15R/nTWTJKxjumbs05bqwRKLTMsVj6kpDDY/EqhHMvB6Xm70
# z+xDGki9xsBOTGRO7GdqGlWEKfnwUIPjipwy9crhsjSe121XrP8uwmmDBL1tOLgc
# L+geqtruzJgFmo3rOBGxXA==
# =4paq
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 25 Jul 2023 11:24:31 BST
# gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg: issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* tag 'pull-target-arm-20230725' of https://git.linaro.org/people/pmaydell/qemu-arm:
tests/decode: Suppress "error: " string for expected-failure tests
For curses display, recognize a few more control keys
target/arm: Special case M-profile in debug_helper.c code
scripts/git-submodule.sh: Don't rely on non-POSIX 'read' behaviour
hw/arm/smmu: Handle big-endian hosts correctly
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/qapi/migration.json b/qapi/migration.json
index 47dfef0..2a6565a 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -67,13 +67,13 @@
{ 'struct': 'MigrationStats',
'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
'duplicate': 'int', 'skipped': 'int', 'normal': 'int',
- 'normal-bytes': 'int', 'dirty-pages-rate' : 'int',
- 'mbps' : 'number', 'dirty-sync-count' : 'int',
- 'postcopy-requests' : 'int', 'page-size' : 'int',
- 'multifd-bytes' : 'uint64', 'pages-per-second' : 'uint64',
- 'precopy-bytes' : 'uint64', 'downtime-bytes' : 'uint64',
- 'postcopy-bytes' : 'uint64',
- 'dirty-sync-missed-zero-copy' : 'uint64' } }
+ 'normal-bytes': 'int', 'dirty-pages-rate': 'int',
+ 'mbps': 'number', 'dirty-sync-count': 'int',
+ 'postcopy-requests': 'int', 'page-size': 'int',
+ 'multifd-bytes': 'uint64', 'pages-per-second': 'uint64',
+ 'precopy-bytes': 'uint64', 'downtime-bytes': 'uint64',
+ 'postcopy-bytes': 'uint64',
+ 'dirty-sync-missed-zero-copy': 'uint64' } }
##
# @XBZRLECacheStats:
@@ -264,7 +264,7 @@
'*cpu-throttle-percentage': 'int',
'*error-desc': 'str',
'*blocked-reasons': ['str'],
- '*postcopy-blocktime' : 'uint32',
+ '*postcopy-blocktime': 'uint32',
'*postcopy-vcpu-blocktime': ['uint32'],
'*compression': 'CompressionStats',
'*socket-address': ['SocketAddress'] } }
@@ -526,7 +526,7 @@
# Since: 1.2
##
{ 'struct': 'MigrationCapabilityStatus',
- 'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+ 'data': { 'capability': 'MigrationCapability', 'state': 'bool' } }
##
# @migrate-set-capabilities:
@@ -1577,7 +1577,7 @@
# Since: 2.9
##
{ 'command': 'xen-set-replication',
- 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
+ 'data': { 'enable': 'bool', 'primary': 'bool', '*failover': 'bool' },
'if': 'CONFIG_REPLICATION' }
##
@@ -1745,14 +1745,13 @@
##
# @DirtyRateStatus:
#
-# An enumeration of dirtyrate status.
+# Dirty page rate measurement status.
#
-# @unstarted: the dirtyrate thread has not been started.
+# @unstarted: measuring thread has not been started yet
#
-# @measuring: the dirtyrate thread is measuring.
+# @measuring: measuring thread is running
#
-# @measured: the dirtyrate thread has measured and results are
-# available.
+# @measured: dirty page rate is measured and the results are available
#
# Since: 5.2
##
@@ -1762,13 +1761,14 @@
##
# @DirtyRateMeasureMode:
#
-# An enumeration of mode of measuring dirtyrate.
+# Method used to measure dirty page rate. Differences between
+# available methods are explained in @calc-dirty-rate.
#
-# @page-sampling: calculate dirtyrate by sampling pages.
+# @page-sampling: use page sampling
#
-# @dirty-ring: calculate dirtyrate by dirty ring.
+# @dirty-ring: use dirty ring
#
-# @dirty-bitmap: calculate dirtyrate by dirty bitmap.
+# @dirty-bitmap: use dirty bitmap
#
# Since: 6.2
##
@@ -1778,25 +1778,24 @@
##
# @DirtyRateInfo:
#
-# Information about current dirty page rate of vm.
+# Information about measured dirty page rate.
#
# @dirty-rate: an estimate of the dirty page rate of the VM in units
-# of MB/s, present only when estimating the rate has completed.
+# of MiB/s. Value is present only when @status is 'measured'.
#
-# @status: status containing dirtyrate query status includes
-# 'unstarted' or 'measuring' or 'measured'
+# @status: current status of dirty page rate measurements
#
# @start-time: start time in units of second for calculation
#
-# @calc-time: time in units of second for sample dirty pages
+# @calc-time: time period for which dirty page rate was measured
+# (in seconds)
#
-# @sample-pages: page count per GB for sample dirty pages the default
-# value is 512 (since 6.1)
+# @sample-pages: number of sampled pages per GiB of guest memory.
+# Valid only in page-sampling mode (Since 6.1)
#
-# @mode: mode containing method of calculate dirtyrate includes
-# 'page-sampling' and 'dirty-ring' (Since 6.2)
+# @mode: mode that was used to measure dirty page rate (Since 6.2)
#
-# @vcpu-dirty-rate: dirtyrate for each vcpu if dirty-ring mode
+# @vcpu-dirty-rate: dirty rate for each vCPU if dirty-ring mode was
# specified (Since 6.2)
#
# Since: 5.2
@@ -1813,15 +1812,49 @@
##
# @calc-dirty-rate:
#
-# start calculating dirty page rate for vm
+# Start measuring dirty page rate of the VM. Results can be retrieved
+# with @query-dirty-rate after measurements are completed.
#
-# @calc-time: time in units of second for sample dirty pages
+# Dirty page rate is the number of pages changed in a given time
+# period expressed in MiB/s. The following methods of calculation are
+# available:
#
-# @sample-pages: page count per GB for sample dirty pages the default
-# value is 512 (since 6.1)
+# 1. In page sampling mode, a random subset of pages are selected and
+# hashed twice: once at the beginning of measurement time period,
+# and once again at the end. If two hashes for some page are
+# different, the page is counted as changed. Since this method
+# relies on sampling and hashing, calculated dirty page rate is
+# only an estimate of its true value. Increasing @sample-pages
+# improves estimation quality at the cost of higher computational
+# overhead.
#
-# @mode: mechanism of calculating dirtyrate includes 'page-sampling'
-# and 'dirty-ring' (Since 6.1)
+# 2. Dirty bitmap mode captures writes to memory (for example by
+# temporarily revoking write access to all pages) and counting page
+# faults. Information about modified pages is collected into a
+# bitmap, where each bit corresponds to one guest page. This mode
+# requires that KVM accelerator property "dirty-ring-size" is *not*
+# set.
+#
+# 3. Dirty ring mode is similar to dirty bitmap mode, but the
+# information about modified pages is collected into ring buffer.
+# This mode tracks page modification per each vCPU separately. It
+# requires that KVM accelerator property "dirty-ring-size" is set.
+#
+# @calc-time: time period in units of second for which dirty page rate
+# is calculated. Note that larger @calc-time values will
+# typically result in smaller dirty page rates because page
+# dirtying is a one-time event. Once some page is counted as
+# dirty during @calc-time period, further writes to this page will
+# not increase dirty page rate anymore.
+#
+# @sample-pages: number of sampled pages per each GiB of guest memory.
+# Default value is 512. For 4KiB guest pages this corresponds to
+# sampling ratio of 0.2%. This argument is used only in page
+# sampling mode. (Since 6.1)
+#
+# @mode: mechanism for tracking dirty pages. Default value is
+# 'page-sampling'. Others are 'dirty-bitmap' and 'dirty-ring'.
+# (Since 6.1)
#
# Since: 5.2
#
@@ -1838,9 +1871,21 @@
##
# @query-dirty-rate:
#
-# query dirty page rate in units of MB/s for vm
+# Query results of the most recent invocation of @calc-dirty-rate.
#
# Since: 5.2
+#
+# Examples:
+#
+# 1. Measurement is in progress:
+#
+# <- {"status": "measuring", "sample-pages": 512,
+# "mode": "page-sampling", "start-time": 3665220, "calc-time": 10}
+#
+# 2. Measurement has been completed:
+#
+# <- {"status": "measured", "sample-pages": 512, "dirty-rate": 108,
+# "mode": "page-sampling", "start-time": 3665220, "calc-time": 10}
##
{ 'command': 'query-dirty-rate', 'returns': 'DirtyRateInfo' }
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ed04027..fa371ca 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -342,6 +342,7 @@
uint64_t CSR_DBG;
uint64_t CSR_DERA;
uint64_t CSR_DSAVE;
+ uint64_t CSR_CPUID;
#ifndef CONFIG_USER_ONLY
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
index 6526367..5534155 100644
--- a/target/loongarch/csr_helper.c
+++ b/target/loongarch/csr_helper.c
@@ -35,6 +35,15 @@
return v;
}
+target_ulong helper_csrrd_cpuid(CPULoongArchState *env)
+{
+ LoongArchCPU *lac = env_archcpu(env);
+
+ env->CSR_CPUID = CPU(lac)->cpu_index;
+
+ return env->CSR_CPUID;
+}
+
target_ulong helper_csrrd_tval(CPULoongArchState *env)
{
LoongArchCPU *cpu = env_archcpu(env);
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index b9de77d..ffb1e0b 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -98,6 +98,7 @@
#ifndef CONFIG_USER_ONLY
/* CSRs helper */
DEF_HELPER_1(csrrd_pgd, i64, env)
+DEF_HELPER_1(csrrd_cpuid, i64, env)
DEF_HELPER_1(csrrd_tval, i64, env)
DEF_HELPER_2(csrwr_estat, i64, env, tl)
DEF_HELPER_2(csrwr_asid, i64, env, tl)
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc b/target/loongarch/insn_trans/trans_privileged.c.inc
index 02bca7c..9c9de09 100644
--- a/target/loongarch/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/insn_trans/trans_privileged.c.inc
@@ -99,13 +99,7 @@
CSR_OFF(PWCH),
CSR_OFF(STLBPS),
CSR_OFF(RVACFG),
- [LOONGARCH_CSR_CPUID] = {
- .offset = (int)offsetof(CPUState, cpu_index)
- - (int)offsetof(LoongArchCPU, env),
- .flags = CSRFL_READONLY,
- .readfn = NULL,
- .writefn = NULL
- },
+ CSR_OFF_FUNCS(CPUID, CSRFL_READONLY, gen_helper_csrrd_cpuid, NULL),
CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY),
CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY),
CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY),
diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
index 228aa9f..3da337f 100644
--- a/target/s390x/tcg/excp_helper.c
+++ b/target/s390x/tcg/excp_helper.c
@@ -639,7 +639,7 @@
void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code,
uint32_t monitor_class)
{
- g_assert(monitor_class <= 0xff);
+ g_assert(monitor_class <= 0xf);
if (env->cregs[8] & (0x8000 >> monitor_class)) {
monitor_event(env, monitor_code, monitor_class, GETPC());
diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c
index 4b7fa58..3d941ed 100644
--- a/target/s390x/tcg/fpu_helper.c
+++ b/target/s390x/tcg/fpu_helper.c
@@ -52,7 +52,8 @@
s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
- s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0;
+ s390_exc |= (exc & (float_flag_inexact | float_flag_invalid_cvti)) ?
+ S390_IEEE_MASK_INEXACT : 0;
return s390_exc;
}
diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
index 457ed25..86a509b 100644
--- a/target/s390x/tcg/insn-data.h.inc
+++ b/target/s390x/tcg/insn-data.h.inc
@@ -157,7 +157,7 @@
C(0xb2fa, NIAI, E, EH, 0, 0, 0, 0, 0, 0)
/* CHECKSUM */
- C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
+ C(0xb241, CKSM, RRE, Z, r1_o, ra2_E, new, r1_32, cksm, 0)
/* COPY SIGN */
F(0xb372, CPSDR, RRF_b, FPSSH, f3, f2, new, f1, cps, 0, IF_AFP1 | IF_AFP2 | IF_AFP3)
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index f417fb1..8410325 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -667,6 +667,11 @@
HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
mask, addr);
+ if (!mask) {
+ /* Recognize access exceptions for the first byte */
+ probe_read(env, addr, 1, cpu_mmu_index(env, false), ra);
+ }
+
while (mask) {
if (mask & 8) {
uint8_t d = cpu_ldub_data_ra(env, addr, ra);
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
index 6661b27..84d76f1 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -2515,6 +2515,12 @@
ccm = ((1ull << len) - 1) << pos;
break;
+ case 0:
+ /* Recognize access exceptions for the first byte. */
+ tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB);
+ gen_op_movi_cc(s, 0);
+ return DISAS_NEXT;
+
default:
/* This is going to be a sequence of loads and inserts. */
pos = base + 32 - 8;
@@ -3171,9 +3177,9 @@
static DisasJumpType op_mc(DisasContext *s, DisasOps *o)
{
- const uint16_t monitor_class = get_field(s, i2);
+ const uint8_t monitor_class = get_field(s, i2);
- if (monitor_class & 0xff00) {
+ if (monitor_class & 0xf0) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
@@ -5779,6 +5785,12 @@
}
#define SPEC_in2_ra2 0
+static void in2_ra2_E(DisasContext *s, DisasOps *o)
+{
+ return in2_ra2(s, o);
+}
+#define SPEC_in2_ra2_E SPEC_r2_even
+
static void in2_a2(DisasContext *s, DisasOps *o)
{
int x2 = have_field(s, x2) ? get_field(s, x2) : 0;
diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc
index 43dfbfd..f8df121 100644
--- a/target/s390x/tcg/translate_vx.c.inc
+++ b/target/s390x/tcg/translate_vx.c.inc
@@ -3047,7 +3047,7 @@
const uint8_t m5 = get_field(s, m5);
gen_helper_gvec_3_ptr *fn;
- if (m6 == 5 || m6 == 6 || m6 == 7 || m6 > 13) {
+ if (m6 == 5 || m6 == 6 || m6 == 7 || m6 >= 13) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
diff --git a/tests/avocado/machine_s390_ccw_virtio.py b/tests/avocado/machine_s390_ccw_virtio.py
index 78152f2..e7a2a20 100644
--- a/tests/avocado/machine_s390_ccw_virtio.py
+++ b/tests/avocado/machine_s390_ccw_virtio.py
@@ -159,7 +159,6 @@ def test_s390x_devices(self):
'MemTotal: 115640 kB')
- @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
def test_s390x_fedora(self):
"""
@@ -229,31 +228,35 @@ def test_s390x_fedora(self):
# writing to the framebuffer. Since the PPM is uncompressed, we then
# can simply read the written "magic bytes" back from the PPM file to
# check whether the framebuffer is working as expected.
- self.log.info("Test screendump of virtio-gpu device")
- exec_command_and_wait_for_pattern(self,
+ # Unfortunately, this test is flaky, so we don't run it by default
+ if os.getenv('QEMU_TEST_FLAKY_TESTS'):
+ self.log.info("Test screendump of virtio-gpu device")
+ exec_command_and_wait_for_pattern(self,
'while ! (dmesg | grep gpudrmfb) ; do sleep 1 ; done',
'virtio_gpudrmfb frame buffer device')
- exec_command_and_wait_for_pattern(self,
- 'echo -e "\e[?25l" > /dev/tty0', ':/#')
- exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do '
- 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;'
- 'done',
- ':/#')
- exec_command_and_wait_for_pattern(self,
- 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt',
- '12+0 records out')
- with tempfile.NamedTemporaryFile(suffix='.ppm',
- prefix='qemu-scrdump-') as ppmfile:
- self.vm.command('screendump', filename=ppmfile.name)
- ppmfile.seek(0)
- line = ppmfile.readline()
- self.assertEqual(line, b"P6\n")
- line = ppmfile.readline()
- self.assertEqual(line, b"1280 800\n")
- line = ppmfile.readline()
- self.assertEqual(line, b"255\n")
- line = ppmfile.readline(256)
- self.assertEqual(line, b"The quick fox jumps over a lazy dog\n")
+ exec_command_and_wait_for_pattern(self,
+ 'echo -e "\e[?25l" > /dev/tty0', ':/#')
+ exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do '
+ 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;'
+ 'done',
+ ':/#')
+ exec_command_and_wait_for_pattern(self,
+ 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt',
+ '12+0 records out')
+ with tempfile.NamedTemporaryFile(suffix='.ppm',
+ prefix='qemu-scrdump-') as ppmfile:
+ self.vm.command('screendump', filename=ppmfile.name)
+ ppmfile.seek(0)
+ line = ppmfile.readline()
+ self.assertEqual(line, b"P6\n")
+ line = ppmfile.readline()
+ self.assertEqual(line, b"1280 800\n")
+ line = ppmfile.readline()
+ self.assertEqual(line, b"255\n")
+ line = ppmfile.readline(256)
+ self.assertEqual(line, b"The quick fox jumps over a lazy dog\n")
+ else:
+ self.log.info("Skipped flaky screendump of virtio-gpu device test")
# Hot-plug a virtio-crypto device and see whether it gets accepted
self.log.info("Test hot-plug virtio-crypto device")
diff --git a/tests/avocado/migration.py b/tests/avocado/migration.py
index 8b2ec0e..fdc1d23 100644
--- a/tests/avocado/migration.py
+++ b/tests/avocado/migration.py
@@ -134,21 +134,3 @@ def test_migration_with_unix(self):
def test_migration_with_exec(self):
self.migration_with_exec()
-
-
-@skipUnless('s390x' in os.uname()[4], "host != target")
-class S390X(MigrationTest):
- """
- :avocado: tags=arch:s390x
- :avocado: tags=machine:s390-ccw-virtio
- :avocado: tags=cpu:qemu
- """
-
- def test_migration_with_tcp_localhost(self):
- self.migration_with_tcp_localhost()
-
- def test_migration_with_unix(self):
- self.migration_with_unix()
-
- def test_migration_with_exec(self):
- self.migration_with_exec()
diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target
index 242c7b0..76345b6 100644
--- a/tests/tcg/s390x/Makefile.softmmu-target
+++ b/tests/tcg/s390x/Makefile.softmmu-target
@@ -16,13 +16,18 @@
ASM_TESTS = \
bal \
+ cksm \
+ clm \
exrl-ssm-early \
+ icm \
sam \
lpsw \
lpswe-early \
lra \
+ mc \
ssm-early \
stosm-early \
+ stpq \
unaligned-lowcore
include $(S390X_SRC)/pgm-specification.mak
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 19fbbc6..1fc9809 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -39,12 +39,17 @@
TESTS+=epsw
TESTS+=larl
TESTS+=mdeb
+TESTS+=cgebra
+TESTS+=clgebr
cdsg: CFLAGS+=-pthread
cdsg: LDFLAGS+=-pthread
rxsbg: CFLAGS+=-O2
+cgebra: LDFLAGS+=-lm
+clgebr: LDFLAGS+=-lm
+
include $(S390X_SRC)/pgm-specification.mak
$(PGM_SPECIFICATION_TESTS): pgm-specification-user.o
$(PGM_SPECIFICATION_TESTS): LDFLAGS+=pgm-specification-user.o
@@ -53,6 +58,7 @@
Z13_TESTS=vistr
Z13_TESTS+=lcbb
Z13_TESTS+=locfhr
+Z13_TESTS+=vcksm
$(Z13_TESTS): CFLAGS+=-march=z13 -O2
TESTS+=$(Z13_TESTS)
diff --git a/tests/tcg/s390x/cgebra.c b/tests/tcg/s390x/cgebra.c
new file mode 100644
index 0000000..f91e10d
--- /dev/null
+++ b/tests/tcg/s390x/cgebra.c
@@ -0,0 +1,32 @@
+/*
+ * Test the CGEBRA instruction.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include <assert.h>
+#include <fenv.h>
+#include <stdlib.h>
+
+int main(void)
+{
+ float r2 = 1E+300;
+ long long r1;
+ int cc;
+
+ feclearexcept(FE_ALL_EXCEPT);
+ asm("cgebra %[r1],%[m3],%[r2],%[m4]\n"
+ "ipm %[cc]\n"
+ : [r1] "=r" (r1)
+ , [cc] "=r" (cc)
+ : [m3] "i" (5) /* round toward 0 */
+ , [r2] "f" (r2)
+ , [m4] "i" (8) /* bit 0 is set, but must be ignored; XxC is not set */
+ : "cc");
+ cc >>= 28;
+
+ assert(r1 == 0x7fffffffffffffffLL);
+ assert(cc == 3);
+ assert(fetestexcept(FE_ALL_EXCEPT) == (FE_INVALID | FE_INEXACT));
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/s390x/cksm.S b/tests/tcg/s390x/cksm.S
new file mode 100644
index 0000000..563fd3d
--- /dev/null
+++ b/tests/tcg/s390x/cksm.S
@@ -0,0 +1,29 @@
+ .org 0x8e
+program_interruption_code:
+ .org 0x1d0 /* program new PSW */
+ .quad 0,pgm
+ .org 0x200 /* lowcore padding */
+ .globl _start
+_start:
+ lmg %r0,%r1,cksm_args
+ cksm %r2,%r0
+ c %r2,cksm_exp
+ jne failure
+ .insn rre,0xb2410000,%r2,%r15 /* cksm %r2,%r15 */
+failure:
+ lpswe failure_psw
+pgm:
+ chhsi program_interruption_code,6 /* specification exception? */
+ jne failure
+ lpswe success_psw
+cksm_args:
+ .quad cksm_buf, 16
+cksm_buf:
+ .quad 0xaaaabbbbcccc0000, 0x12345678
+cksm_exp:
+ .long 0x89ab1234
+ .align 8
+success_psw:
+ .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000000000000,0 /* disabled wait */
diff --git a/tests/tcg/s390x/clgebr.c b/tests/tcg/s390x/clgebr.c
new file mode 100644
index 0000000..d491899
--- /dev/null
+++ b/tests/tcg/s390x/clgebr.c
@@ -0,0 +1,32 @@
+/*
+ * Test the CLGEBR instruction.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include <assert.h>
+#include <fenv.h>
+#include <stdlib.h>
+
+int main(void)
+{
+ float r2 = -1;
+ long long r1;
+ int cc;
+
+ feclearexcept(FE_ALL_EXCEPT);
+ asm("clgebr %[r1],%[m3],%[r2],%[m4]\n"
+ "ipm %[cc]\n"
+ : [r1] "=r" (r1)
+ , [cc] "=r" (cc)
+ : [m3] "i" (5) /* round toward 0 */
+ , [r2] "f" (r2)
+ , [m4] "i" (8) /* bit 0 is set, but must be ignored; XxC is not set */
+ : "cc");
+ cc >>= 28;
+
+ assert(r1 == 0);
+ assert(cc == 3);
+ assert(fetestexcept(FE_ALL_EXCEPT) == (FE_INVALID | FE_INEXACT));
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/s390x/clm.S b/tests/tcg/s390x/clm.S
new file mode 100644
index 0000000..17156a8
--- /dev/null
+++ b/tests/tcg/s390x/clm.S
@@ -0,0 +1,29 @@
+ .org 0x8e
+program_interruption_code:
+ .org 0x1d0 /* program new PSW */
+ .quad 0,pgm
+ .org 0x200 /* lowcore padding */
+ .globl _start
+_start:
+ lgrl %r0,op1
+ clm %r0,6,op2
+ jle failure
+ lgrl %r1,bad_addr
+ clm %r0,0,0(%r1)
+failure:
+ lpswe failure_psw
+pgm:
+ chhsi program_interruption_code,5 /* addressing exception? */
+ jne failure
+ lpswe success_psw
+ .align 8
+op1:
+ .quad 0x1234567887654321
+op2:
+ .quad 0x3456789abcdef012
+bad_addr:
+ .quad 0xffffffff00000000
+success_psw:
+ .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000000000000,0 /* disabled wait */
diff --git a/tests/tcg/s390x/icm.S b/tests/tcg/s390x/icm.S
new file mode 100644
index 0000000..d24d1f5
--- /dev/null
+++ b/tests/tcg/s390x/icm.S
@@ -0,0 +1,32 @@
+ .org 0x8e
+program_interruption_code:
+ .org 0x1d0 /* program new PSW */
+ .quad 0,pgm
+ .org 0x200 /* lowcore padding */
+ .globl _start
+_start:
+ lgrl %r0,op1
+ icm %r0,10,op2
+ cg %r0,exp
+ jne failure
+ lgrl %r1,bad_addr
+ icm %r0,0,0(%r1)
+failure:
+ lpswe failure_psw
+pgm:
+ chhsi program_interruption_code,5 /* addressing exception? */
+ jne failure
+ lpswe success_psw
+ .align 8
+op1:
+ .quad 0x1234567887654321
+op2:
+ .quad 0x0011223344556677
+exp:
+ .quad 0x1234567800651121
+bad_addr:
+ .quad 0xffffffff00000000
+success_psw:
+ .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000000000000,0 /* disabled wait */
diff --git a/tests/tcg/s390x/mc.S b/tests/tcg/s390x/mc.S
new file mode 100644
index 0000000..e7466bb
--- /dev/null
+++ b/tests/tcg/s390x/mc.S
@@ -0,0 +1,56 @@
+ .org 0x8d
+ilc:
+ .org 0x8e
+program_interruption_code:
+ .org 0x94
+monitor_class:
+ .org 0xb0
+monitor_code:
+ .org 0x150
+program_old_psw:
+ .org 0x1d0 /* program new PSW */
+ .quad 0x180000000,pgm /* 64-bit mode */
+ .org 0x200 /* lowcore padding */
+ .globl _start
+_start:
+ stctg %c8,%c8,c8 /* enable only monitor class 1 */
+ mvhhi c8+6,0x4000
+ lctlg %c8,%c8,c8
+mc_nop:
+ mc 123,0
+mc_monitor_event:
+ mc 321,1
+ j failure
+mc_specification:
+ mc 333,16
+ j failure
+pgm:
+ lgrl %r0,program_old_psw+8 /* ilc adjustment */
+ llgc %r1,ilc
+ sgr %r0,%r1
+ larl %r1,mc_monitor_event /* dispatch based on old PSW */
+ cgrje %r0,%r1,pgm_monitor_event
+ larl %r1,mc_specification
+ cgrje %r0,%r1,pgm_specification
+ j failure
+pgm_monitor_event:
+ chhsi program_interruption_code,0x40 /* monitor event? */
+ jne failure
+ chhsi monitor_class,1 /* class from mc_monitor_event? */
+ jne failure
+ cghsi monitor_code,321 /* code from mc_monitor_event? */
+ jne failure
+ j mc_specification /* next test */
+pgm_specification:
+ chhsi program_interruption_code,6 /* specification exception? */
+ jne failure
+ lpswe success_psw
+failure:
+ lpswe failure_psw
+ .align 8
+c8:
+ .quad 0
+success_psw:
+ .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000000000000,0 /* disabled wait */
diff --git a/tests/tcg/s390x/stpq.S b/tests/tcg/s390x/stpq.S
new file mode 100644
index 0000000..687a52e
--- /dev/null
+++ b/tests/tcg/s390x/stpq.S
@@ -0,0 +1,20 @@
+ .org 0x200 /* lowcore padding */
+ .globl _start
+_start:
+ lgrl %r0,value
+ lgrl %r1,value+8
+ stpq %r0,stored_value
+ clc stored_value(16),value
+ jne failure
+ lpswe success_psw
+failure:
+ lpswe failure_psw
+ .align 16
+value:
+ .quad 0x1234567887654321, 0x8765432112345678
+stored_value:
+ .quad 0, 0
+success_psw:
+ .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000000000000,0 /* disabled wait */
diff --git a/tests/tcg/s390x/vcksm.c b/tests/tcg/s390x/vcksm.c
new file mode 100644
index 0000000..452daaa
--- /dev/null
+++ b/tests/tcg/s390x/vcksm.c
@@ -0,0 +1,31 @@
+/*
+ * Test the VCKSM instruction.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "vx.h"
+
+int main(void)
+{
+ S390Vector v1;
+ S390Vector v2 = {
+ .d[0] = 0xb2261c8140edce49ULL,
+ .d[1] = 0x387bf5a433af39d1ULL,
+ };
+ S390Vector v3 = {
+ .d[0] = 0x73b03d2c7f9e654eULL,
+ .d[1] = 0x23d74e51fb479877ULL,
+ };
+ S390Vector exp = {.d[0] = 0xdedd7f8eULL, .d[1] = 0ULL};
+
+ asm volatile("vcksm %[v1],%[v2],%[v3]"
+ : [v1] "=v" (v1.v)
+ : [v2] "v" (v2.v)
+ , [v3] "v" (v3.v));
+ assert(memcmp(&v1, &exp, sizeof(v1)) == 0);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/s390x/vx.h b/tests/tcg/s390x/vx.h
index 02e7fd5..00701db 100644
--- a/tests/tcg/s390x/vx.h
+++ b/tests/tcg/s390x/vx.h
@@ -1,6 +1,8 @@
#ifndef QEMU_TESTS_S390X_VX_H
#define QEMU_TESTS_S390X_VX_H
+#include <stdint.h>
+
typedef union S390Vector {
uint64_t d[2]; /* doubleword */
uint32_t w[4]; /* word */