diff options
-rw-r--r-- | hw/s390x/css.c | 2 | ||||
-rw-r--r-- | target-s390x/cpu.h | 4 | ||||
-rw-r--r-- | target-s390x/ioinst.c | 19 | ||||
-rw-r--r-- | target-s390x/ioinst.h | 7 |
4 files changed, 24 insertions, 8 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 113ac9a893..84efd4ad87 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -852,7 +852,7 @@ int css_do_stcrw(CRW *crw) return ret; } -int css_do_tpi(uint64_t addr, int lowcore) +int css_do_tpi(IOIntCode *int_code, int lowcore) { /* No pending interrupts for !KVM. */ return 0; diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index ce12fa46bc..9be4a475a3 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -413,7 +413,7 @@ int css_do_hsch(SubchDev *sch); int css_do_ssch(SubchDev *sch, ORB *orb); int css_do_tsch(SubchDev *sch, IRB *irb); int css_do_stcrw(CRW *crw); -int css_do_tpi(uint64_t addr, int lowcore); +int css_do_tpi(IOIntCode *int_code, int lowcore); int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid, int rfmt, void *buf); void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo); @@ -471,7 +471,7 @@ static inline int css_do_stcrw(CRW *crw) { return 1; } -static inline int css_do_tpi(uint64_t addr, int lowcore) +static inline int css_do_tpi(IOIntCode *int_code, int lowcore) { return 0; } diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c index 4ef2d73a43..e3531f365e 100644 --- a/target-s390x/ioinst.c +++ b/target-s390x/ioinst.c @@ -619,16 +619,25 @@ int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb) { uint64_t addr; int lowcore; + IOIntCode *int_code; + hwaddr len, orig_len; + int ret; trace_ioinst("tpi"); addr = decode_basedisp_s(env, ipb); lowcore = addr ? 0 : 1; - if (addr < 8192) { - addr += env->psa; - } else if ((env->psa <= addr) && (addr < env->psa + 8192)) { - addr -= env->psa; + len = lowcore ? 8 /* two words */ : 12 /* three words */; + orig_len = len; + int_code = s390_cpu_physical_memory_map(env, addr, &len, 1); + if (!int_code || (len != orig_len)) { + program_interrupt(env, PGM_SPECIFICATION, 2); + ret = -EIO; + goto out; } - return css_do_tpi(addr, lowcore); + ret = css_do_tpi(int_code, lowcore); +out: + s390_cpu_physical_memory_unmap(env, int_code, len, 1); + return ret; } #define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc) diff --git a/target-s390x/ioinst.h b/target-s390x/ioinst.h index a59742c3c6..d5a43f4a71 100644 --- a/target-s390x/ioinst.h +++ b/target-s390x/ioinst.h @@ -195,6 +195,13 @@ typedef struct CRW { #define CRW_RSC_SUBCH 0x3 #define CRW_RSC_CHP 0x4 +/* I/O interruption code */ +typedef struct IOIntCode { + uint32_t subsys_id; + uint32_t intparm; + uint32_t interrupt_id; +} QEMU_PACKED IOIntCode; + /* schid disintegration */ #define IOINST_SCHID_ONE(_schid) ((_schid & 0x00010000) >> 16) #define IOINST_SCHID_M(_schid) ((_schid & 0x00080000) >> 19) |