diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-06-15 13:24:50 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-06-15 13:24:51 +0100 |
commit | 46bca5404b08201bb9df1ac32bc88fc7e6db1f74 (patch) | |
tree | d4501d9f7027a6cbe51c3ab828d6f75a8f6d5087 /target-s390x | |
parent | f3e3b083d4c266ea864ae3c83da49d4086857679 (diff) | |
parent | 8369e339d24f365750da456588e742674c153437 (diff) | |
download | qemu-46bca5404b08201bb9df1ac32bc88fc7e6db1f74.tar.gz qemu-46bca5404b08201bb9df1ac32bc88fc7e6db1f74.tar.bz2 qemu-46bca5404b08201bb9df1ac32bc88fc7e6db1f74.zip |
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20150615' into staging
s390x/kvm/watchdog
1. Implement a diag288 based watchdog
2. Fix virtio-ccw BIOS for gcc >= 4.9
# gpg: Signature made Mon Jun 15 12:36:25 2015 BST using RSA key ID B5A61C7C
# gpg: Good signature from "Christian Borntraeger (IBM) <borntraeger@de.ibm.com>"
* remotes/borntraeger/tags/s390x-20150615:
s390/bios: build with -fdelete-null-pointer-checks
watchdog: Add new Virtual Watchdog action INJECT-NMI
nmi: Implement inject_nmi() for non-monitor context use
s390x/watchdog: diag288 migration support
s390x/kvm: diag288 instruction interception and handling
s390x/watchdog: introduce diag288 watchdog device
watchdog: change option wording to allow for more watchdogs
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-s390x')
-rw-r--r-- | target-s390x/cpu.h | 1 | ||||
-rw-r--r-- | target-s390x/kvm.c | 18 | ||||
-rw-r--r-- | target-s390x/misc_helper.c | 29 |
3 files changed, 48 insertions, 0 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 584e74b89a..d63eb51186 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1100,6 +1100,7 @@ uint32_t set_cc_nz_f128(float128 v); /* misc_helper.c */ #ifndef CONFIG_USER_ONLY +int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3); void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3); #endif void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index f6f61b9619..b02ff8d61d 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -98,6 +98,7 @@ #define PRIV_E3_MPCIFC 0xd0 #define PRIV_E3_STPCIFC 0xd4 +#define DIAG_TIMEREVENT 0x288 #define DIAG_IPL 0x308 #define DIAG_KVM_HYPERCALL 0x500 #define DIAG_KVM_BREAKPOINT 0x501 @@ -1267,6 +1268,20 @@ static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) return ret; } +static void kvm_handle_diag_288(S390CPU *cpu, struct kvm_run *run) +{ + uint64_t r1, r3; + int rc; + + cpu_synchronize_state(CPU(cpu)); + r1 = (run->s390_sieic.ipa & 0x00f0) >> 4; + r3 = run->s390_sieic.ipa & 0x000f; + rc = handle_diag_288(&cpu->env, r1, r3); + if (rc) { + enter_pgmcheck(cpu, PGM_SPECIFICATION); + } +} + static void kvm_handle_diag_308(S390CPU *cpu, struct kvm_run *run) { uint64_t r1, r3; @@ -1306,6 +1321,9 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb) */ func_code = decode_basedisp_rs(&cpu->env, ipb, NULL) & DIAG_KVM_CODE_MASK; switch (func_code) { + case DIAG_TIMEREVENT: + kvm_handle_diag_288(cpu, run); + break; case DIAG_IPL: kvm_handle_diag_308(cpu, run); break; diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index b375ab724b..6711504221 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -30,6 +30,7 @@ #include <linux/kvm.h> #endif #include "exec/cpu_ldst.h" +#include "hw/watchdog/wdt_diag288.h" #if !defined(CONFIG_USER_ONLY) #include "sysemu/cpus.h" @@ -153,6 +154,34 @@ static int load_normal_reset(S390CPU *cpu) return 0; } +int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) +{ + uint64_t func = env->regs[r1]; + uint64_t timeout = env->regs[r1 + 1]; + uint64_t action = env->regs[r3]; + Object *obj; + DIAG288State *diag288; + DIAG288Class *diag288_class; + + if (r1 % 2 || action != 0) { + return -1; + } + + /* Timeout must be more than 15 seconds except for timer deletion */ + if (func != WDT_DIAG288_CANCEL && timeout < 15) { + return -1; + } + + obj = object_resolve_path_type("", TYPE_WDT_DIAG288, NULL); + if (!obj) { + return -1; + } + + diag288 = DIAG288(obj); + diag288_class = DIAG288_GET_CLASS(diag288); + return diag288_class->handle_timer(diag288, func, timeout); +} + #define DIAG_308_RC_OK 0x0001 #define DIAG_308_RC_NO_CONF 0x0102 #define DIAG_308_RC_INVALID 0x0402 |