mirror of https://github.com/xemu-project/xemu.git
s390x/kvm: diag288 instruction interception and handling
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>
This commit is contained in:
parent
188f24c2c1
commit
8fc639af4b
|
@ -1100,6 +1100,7 @@ uint32_t set_cc_nz_f128(float128 v);
|
||||||
|
|
||||||
/* misc_helper.c */
|
/* misc_helper.c */
|
||||||
#ifndef CONFIG_USER_ONLY
|
#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);
|
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
|
||||||
#endif
|
#endif
|
||||||
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
|
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
|
||||||
|
|
|
@ -98,6 +98,7 @@
|
||||||
#define PRIV_E3_MPCIFC 0xd0
|
#define PRIV_E3_MPCIFC 0xd0
|
||||||
#define PRIV_E3_STPCIFC 0xd4
|
#define PRIV_E3_STPCIFC 0xd4
|
||||||
|
|
||||||
|
#define DIAG_TIMEREVENT 0x288
|
||||||
#define DIAG_IPL 0x308
|
#define DIAG_IPL 0x308
|
||||||
#define DIAG_KVM_HYPERCALL 0x500
|
#define DIAG_KVM_HYPERCALL 0x500
|
||||||
#define DIAG_KVM_BREAKPOINT 0x501
|
#define DIAG_KVM_BREAKPOINT 0x501
|
||||||
|
@ -1267,6 +1268,20 @@ static int handle_hypercall(S390CPU *cpu, struct kvm_run *run)
|
||||||
return ret;
|
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)
|
static void kvm_handle_diag_308(S390CPU *cpu, struct kvm_run *run)
|
||||||
{
|
{
|
||||||
uint64_t r1, r3;
|
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;
|
func_code = decode_basedisp_rs(&cpu->env, ipb, NULL) & DIAG_KVM_CODE_MASK;
|
||||||
switch (func_code) {
|
switch (func_code) {
|
||||||
|
case DIAG_TIMEREVENT:
|
||||||
|
kvm_handle_diag_288(cpu, run);
|
||||||
|
break;
|
||||||
case DIAG_IPL:
|
case DIAG_IPL:
|
||||||
kvm_handle_diag_308(cpu, run);
|
kvm_handle_diag_308(cpu, run);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <linux/kvm.h>
|
#include <linux/kvm.h>
|
||||||
#endif
|
#endif
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "hw/watchdog/wdt_diag288.h"
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
|
@ -153,6 +154,34 @@ static int load_normal_reset(S390CPU *cpu)
|
||||||
return 0;
|
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_OK 0x0001
|
||||||
#define DIAG_308_RC_NO_CONF 0x0102
|
#define DIAG_308_RC_NO_CONF 0x0102
|
||||||
#define DIAG_308_RC_INVALID 0x0402
|
#define DIAG_308_RC_INVALID 0x0402
|
||||||
|
|
Loading…
Reference in New Issue