Skip to content

Commit

Permalink
s390x/kvm: diag288 instruction interception and handling
Browse files Browse the repository at this point in the history
Intercept the diag288 requests from kvm guests, and hand the
requested command to the diag288 watchdog device for further
handling.

Signed-off-by: Xu Wang <gesaint@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
  • Loading branch information
Xu Wang authored and borntraeger committed Jun 11, 2015
1 parent 188f24c commit 8fc639a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
1 change: 1 addition & 0 deletions target-s390x/cpu.h
Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions target-s390x/kvm.c
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
29 changes: 29 additions & 0 deletions target-s390x/misc_helper.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 8fc639a

Please sign in to comment.