diff options
author | Eric Farman <farman@linux.vnet.ibm.com> | 2015-01-14 09:57:16 -0500 |
---|---|---|
committer | Cornelia Huck <cornelia.huck@de.ibm.com> | 2015-05-27 17:52:03 +0200 |
commit | abec53565dce5ed56bff4968d3bed88f6cf68c3c (patch) | |
tree | 93938cd9c187cdec63b61c604ae34a511da03310 /target-s390x/kvm.c | |
parent | fcb79802e07fe06fe24ba97a027d8a1c3a714fa7 (diff) |
s390x: Store Additional Status SIGP order
Add handling for the Store Additional Status at Address order
that exists for the Signal Processor (SIGP) instruction.
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'target-s390x/kvm.c')
-rw-r--r-- | target-s390x/kvm.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index ca8ffcc2a9..61e1321a4b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -1373,6 +1373,28 @@ static void sigp_stop(void *arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +#define ADTL_SAVE_AREA_SIZE 1024 +static int kvm_s390_store_adtl_status(S390CPU *cpu, hwaddr addr) +{ + void *mem; + hwaddr len = ADTL_SAVE_AREA_SIZE; + + mem = cpu_physical_memory_map(addr, &len, 1); + if (!mem) { + return -EFAULT; + } + if (len != ADTL_SAVE_AREA_SIZE) { + cpu_physical_memory_unmap(mem, len, 1, 0); + return -EFAULT; + } + + memcpy(mem, &cpu->env.vregs, 512); + + cpu_physical_memory_unmap(mem, len, 1, len); + + return 0; +} + #define KVM_S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) #define SAVE_AREA_SIZE 512 static int kvm_s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) @@ -1461,6 +1483,36 @@ static void sigp_store_status_at_address(void *arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +static void sigp_store_adtl_status(void *arg) +{ + SigpInfo *si = arg; + + if (!kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS)) { + set_sigp_status(si, SIGP_STAT_INVALID_ORDER); + return; + } + + /* cpu has to be stopped */ + if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) { + set_sigp_status(si, SIGP_STAT_INCORRECT_STATE); + return; + } + + /* parameter must be aligned to 1024-byte boundary */ + if (si->param & 0x3ff) { + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); + return; + } + + cpu_synchronize_state(CPU(si->cpu)); + + if (kvm_s390_store_adtl_status(si->cpu, si->param)) { + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); + return; + } + si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; +} + static void sigp_restart(void *arg) { SigpInfo *si = arg; @@ -1578,6 +1630,9 @@ static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order, case SIGP_STORE_STATUS_ADDR: run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, &si); break; + case SIGP_STORE_ADTL_STATUS: + run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, &si); + break; case SIGP_SET_PREFIX: run_on_cpu(CPU(dst_cpu), sigp_set_prefix, &si); break; |