aboutsummaryrefslogtreecommitdiff
path: root/target-s390x/mem_helper.c
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2015-06-13 00:46:00 +0200
committerAlexander Graf <agraf@suse.de>2015-06-17 12:40:52 +0200
commit311918b979c5364c30392c1054ed77d047a83953 (patch)
tree3ca255bed7666787a2bf045a26a696b4dab97b67 /target-s390x/mem_helper.c
parent8d302e76755b8157373073d7107e31b0b13f80c1 (diff)
target-s390x: PER storage-alteration event support
For the PER storage-alteration event we can use the QEMU watchpoint infrastructure. When PER is enabled or PER control register changed we enable the corresponding watchpoints. When a watchpoint arises we can save the event. Unfortunately the current code does not provide the address space used to trigger the watchpoint. For now we assume it comes from the default ASC. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-s390x/mem_helper.c')
-rw-r--r--target-s390x/mem_helper.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 6427ee9b6b..d03f9fd2f3 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -841,11 +841,17 @@ uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array,
void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
{
S390CPU *cpu = s390_env_get_cpu(env);
+ bool PERchanged = false;
int i;
uint64_t src = a2;
+ uint64_t val;
for (i = r1;; i = (i + 1) % 16) {
- env->cregs[i] = cpu_ldq_data(env, src);
+ val = cpu_ldq_data(env, src);
+ if (env->cregs[i] != val && i >= 9 && i <= 11) {
+ PERchanged = true;
+ }
+ env->cregs[i] = val;
HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
i, src, env->cregs[i]);
src += sizeof(uint64_t);
@@ -855,18 +861,27 @@ void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
}
}
+ if (PERchanged && env->psw.mask & PSW_MASK_PER) {
+ s390_cpu_recompute_watchpoints(CPU(cpu));
+ }
+
tlb_flush(CPU(cpu), 1);
}
void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
{
S390CPU *cpu = s390_env_get_cpu(env);
+ bool PERchanged = false;
int i;
uint64_t src = a2;
+ uint32_t val;
for (i = r1;; i = (i + 1) % 16) {
- env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) |
- cpu_ldl_data(env, src);
+ val = cpu_ldl_data(env, src);
+ if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) {
+ PERchanged = true;
+ }
+ env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | val;
src += sizeof(uint32_t);
if (i == r3) {
@@ -874,6 +889,10 @@ void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
}
}
+ if (PERchanged && env->psw.mask & PSW_MASK_PER) {
+ s390_cpu_recompute_watchpoints(CPU(cpu));
+ }
+
tlb_flush(CPU(cpu), 1);
}