Mercurial > hvf > hvf
changeset 654:57988d03241d
cp/guest: implement Machine Check interrupt issuing
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Thu, 29 Mar 2012 17:44:13 -0400 |
parents | 0d289341e756 |
children | 10df8e1a7d69 |
files | cp/guest/run.c |
diffstat | 1 files changed, 69 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/cp/guest/run.c Thu Mar 29 17:42:13 2012 -0400 +++ b/cp/guest/run.c Thu Mar 29 17:44:13 2012 -0400 @@ -1,5 +1,5 @@ /* - * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * (C) Copyright 2007-2012 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * This file is released under the GPLv2. See the COPYING file for more * details. @@ -18,6 +18,71 @@ memcpy(&cpu->sie_cb.gpsw, gpsa + new, len); } +static int __mch_int(struct virt_sys *sys) +{ + struct virt_cpu *cpu = sys->cpu; + struct mch_int_code *mch; + u64 cr14; + u64 phy; + int ret; + + if (!cpu->sie_cb.gpsw.m) + return 0; + + /* Channel-Report Pending? */ + if (pending_circbuf(&sys->crws)) { + cr14 = cpu->sie_cb.gcr[14]; + + if (cr14 & BIT64(35)) { + con_printf(sys->con, "Time for MCH int...\n"); + + /* get the guest's first page (PSA) */ + ret = virt2phy_current(0, &phy); + if (ret) { + con_printf(sys->con, "Failed to queue up MCH " + "interruption: %d (%s)\n", ret, + errstrings[-ret]); + cpu->state = GUEST_STOPPED; + + return 0; + } + + /* do the PSW swap */ + if (VCPU_ZARCH(cpu)) + __do_psw_swap(cpu, (void*) phy, 0x160, 0x1e0, 16); + else + __do_psw_swap(cpu, (void*) phy, 48, 112, 8); + + mch = (struct mch_int_code*) (phy + 0xe8); + + /* + * The following bits seem to work for Hercules + * (00400F1D 403B0000) + */ + memset(mch, 0, sizeof(struct mch_int_code)); + mch->cp = 1; /* channel report pending */ + mch->wp = 1; + mch->ms = 1; + mch->pm = 1; + mch->ia = 1; + mch->fp = 1; + mch->gr = 1; + mch->cr = 1; + mch->st = 1; + mch->ar = 1; + mch->pr = 1; + mch->fc = 1; + mch->ap = 1; + mch->ct = 1; + mch->cc = 1; + + return 1; + } + } + + return 0; +} + static int __io_int(struct virt_sys *sys) { struct virt_cpu *cpu = sys->cpu; @@ -92,6 +157,9 @@ if (__io_int(sys)) goto go; + if (__mch_int(sys)) + goto go; + if (psw->w) { if (!psw->io && !psw->ex && !psw->m) { con_printf(sys->con, "ENTERED CP DUE TO DISABLED WAIT\n");