summaryrefslogtreecommitdiffstats
path: root/target/s390x/mem_helper.c
diff options
context:
space:
mode:
authorThomas Huth2017-05-18 19:26:40 +0200
committerRichard Henderson2017-06-06 23:34:31 +0200
commitf79f1ca4a20d4070179903bbaafc13f5f90b7873 (patch)
tree5921a73bc3333cde97f964bda0daab4999789405 /target/s390x/mem_helper.c
parentMerge remote-tracking branch 'remotes/xtensa/tags/20170606-xtensa' into staging (diff)
downloadqemu-f79f1ca4a20d4070179903bbaafc13f5f90b7873.tar.gz
qemu-f79f1ca4a20d4070179903bbaafc13f5f90b7873.tar.xz
qemu-f79f1ca4a20d4070179903bbaafc13f5f90b7873.zip
target/s390x: Add support for the TEST BLOCK instruction
TEST BLOCK was likely once used to execute basic memory tests, but nowadays it's just a (slow) way to clear a page. Reviewed-by: Aurelien Jarno <aurelien@aurel32.net> Reviewed-by: David Hildenbrand <david@redhat.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-Id: <1495128400-23759-1-git-send-email-thuth@redhat.com> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target/s390x/mem_helper.c')
-rw-r--r--target/s390x/mem_helper.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index f6e5bcec5d..0c6a0d9612 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "exec/address-spaces.h"
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
@@ -973,6 +974,33 @@ void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
}
}
+uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr)
+{
+ CPUState *cs = CPU(s390_env_get_cpu(env));
+ uint64_t abs_addr;
+ int i;
+
+ real_addr = fix_address(env, real_addr);
+ abs_addr = mmu_real2abs(env, real_addr) & TARGET_PAGE_MASK;
+ if (!address_space_access_valid(&address_space_memory, abs_addr,
+ TARGET_PAGE_SIZE, true)) {
+ program_interrupt(env, PGM_ADDRESSING, 4);
+ return 1;
+ }
+
+ /* Check low-address protection */
+ if ((env->cregs[0] & CR0_LOWPROT) && real_addr < 0x2000) {
+ program_interrupt(env, PGM_PROTECTION, 4);
+ return 1;
+ }
+
+ for (i = 0; i < TARGET_PAGE_SIZE; i += 8) {
+ stq_phys(cs->as, abs_addr + i, 0);
+ }
+
+ return 0;
+}
+
uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
{
/* XXX implement */