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>
This commit is contained in:
Aurelien Jarno 2015-06-13 00:46:00 +02:00 committed by Alexander Graf
parent 8d302e7675
commit 311918b979
5 changed files with 100 additions and 3 deletions

View file

@ -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);
}