From 268846ba93de2529630d623b6ded72cee1221106 Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Wed, 19 Jun 2013 17:27:15 +0200 Subject: s390/kvm: basic implementation of diagnose 308 subcode 6 Linux uses a check for subcode 6 to decide if other subcodes are available. Provide a minimal implementation for subcode 6, as well as for subcode 5. Signed-off-by: Eugene (jno) Dvurechenski Reviewed-by: Cornelia Huck Signed-off-by: Christian Borntraeger [Move code from kvm.c into misc_helper.c] --- target-s390x/misc_helper.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'target-s390x/misc_helper.c') diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 454960aa01..9b4423a031 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -179,6 +179,46 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) return r; } +#ifndef CONFIG_USER_ONLY +#define DIAG_308_RC_NO_CONF 0x0102 +#define DIAG_308_RC_INVALID 0x0402 +void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) +{ + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; + + if (env->psw.mask & PSW_MASK_PSTATE) { + program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC); + return; + } + + if ((subcode & ~0x0ffffULL) || (subcode > 6)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + return; + } + + switch (subcode) { + case 5: + if ((r1 & 1) || (addr & 0x0fffULL)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + return; + } + env->regs[r1+1] = DIAG_308_RC_INVALID; + return; + case 6: + if ((r1 & 1) || (addr & 0x0fffULL)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + return; + } + env->regs[r1+1] = DIAG_308_RC_NO_CONF; + return; + default: + hw_error("Unhandled diag308 subcode %" PRIx64, subcode); + break; + } +} +#endif + /* DIAG */ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem, uint64_t code) -- cgit v1.2.1