s390x/tcg: cleanup and fix program interrupts
v3 cover s390x/tcg: cleanup and fix program interrupts
I have quite some patches on my queue for 2.12. (booting Fedora 26/27 guests, floating interrupts, machine checks, missing instructions ...)
So let's start slowly This series gets rid of program_interrupt() and potential_page_fault(). We now always properly restore the cpu state when injecting/delivering a program interrupt. So there is no need to update the state via potential_page_fault() anymore.
In addition, handling for program interrupts comming via s390_cpu_virt_mem_rw() was missing something for the TCG case. Also fixed.
v2 -> v3:
- "s390x/tcg: don't exit the cpu loop in s390_cpu_virt_mem_rw()" -- don't break old KVM
- Unfortunately not able to come up with a better solution for "s390x: handle exceptions during s390_cpu_virt_mem_rw() correctly (TCG)" so I assume we'll go with this for now.
v1 -> v2:
- renamed program_interrupt_ra() to s390_program_interrupt()
- introduce and use RA_IGNORED for KVM.
- switch to cpu_exit_loop_restore() and don't check if ra is set
- "s390x: handle exceptions during s390_cpu_virt_mem_rw() correctly (TCG)" -> split out "s390x/tcg: don't exit the cpu loop in s390_cpu_virt_mem_rw()"
- "s390x/tcg: use program_interrupt_ra() in SCLP Service Call" -> moved qemu_mutex_lock_iothread(); further up
- "s390x/tcg: drop program_interrupt()"
-> move restore to tcg_s390_program_interrupt() via cpu_loop_exit_restore()
- smaller requested cleanups
David Hildenbrand (16):
s390x/tcg: introduce and use s390_program_interrupt() s390x/tcg: get rid of runtime_exception()
s390x/tcg: rip out dead tpi code
s390x/ioinst: pass the retaddr to all IO instructions s390x/pci: pass the retaddr to all PCI instructions s390x/diag: pass the retaddr into handle_diag_308()
s390x: handle exceptions during s390_cpu_virt_mem_rw() correctly (TCG) s390x/tcg: don't exit the cpu loop in s390_cpu_virt_mem_rw() s390x/tcg: io instructions don't need potential_page_fault() s390x/tcg: use s390_program_interrupt() in SCLP Service Call s390x/tcg: use s390_program_interrupt() in DIAG
s390x/tcg: use s390_program_interrupt() in per_check_exception() s390x/tcg: use s390_program_interrupt() in SACF
s390x/tcg: use s390_program_interrupt() in STSI
s390x/tcg: drop program_interrupt()
s390x/tcg: drop potential_page_fault()
hw/s390x/css.c | 6 --- hw/s390x/s390-pci-inst.c | 90 +++++++++++++++++++--------------- hw/s390x/s390-pci-inst.h | 16 +++--- include/hw/s390x/css.h | 1 - target/s390x/cc_helper.c | 2 +- target/s390x/cpu.h | 5 +- target/s390x/crypto_helper.c | 7 +-- target/s390x/diag.c | 14 +++--- target/s390x/excp_helper.c | 5 +- target/s390x/fpu_helper.c | 2 +- target/s390x/int_helper.c | 14 +++--- target/s390x/internal.h | 35 +++++++------- target/s390x/interrupt.c | 9 ++-- target/s390x/ioinst.c | 113 +++++++++++++++++++------------------------ target/s390x/kvm.c | 43 ++++++++-------- target/s390x/mem_helper.c | 35 +++++--------- target/s390x/misc_helper.c | 52 +++++++------------- target/s390x/mmu_helper.c | 23 +++++++-- target/s390x/translate.c | 27 +---------- 19 files changed, 228 insertions(+), 271 deletions(-)
Signature · 1 line
2.14.3
PATCH v3 1/16 s390x/tcg: introduce and use s390_program_interrupt()
Allows to easily convert more callers of program_interrupt() and to easily introduce new exceptions without forgetting about the cpu state reset.
Use s390_program_interrupt() in places where we already had the same pattern. We will later get rid of program_interrupt().
RA != 0 checks are already done behind the scenes.
--- target/s390x/cpu.h | 2 ++ target/s390x/crypto_helper.c | 7 ++----- target/s390x/excp_helper.c | 5 +---- target/s390x/interrupt.c | 13 +++++++++++++ target/s390x/mem_helper.c | 35 +++++++++++------------------------ target/s390x/misc_helper.c | 3 +-- 6 files changed, 30 insertions(+), 35 deletions(-)
target/s390x/cpu.h +2 -0
@@ -720,6 +720,8 @@ void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,/* automatically detect the instruction length */ #define ILEN_AUTO 0xffvoid program_interrupt (CPUS390XState *env,uint32_t code,int ilen); +void s390_program_interrupt (CPUS390XState *env,uint32_t code,int ilen, +uintptr_t ra);/* service interrupts are floating therefore we must not pass an cpustate */ void s390_sclp_extint (uint32_t parm);
target/s390x/crypto_helper.c +2 -5
@@ -23,7 +23,6 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,const uintptr_t ra =GETPC ();const uint8_t mod = env->regs[0 ] &0x80ULL ;const uint8_t fc = env->regs[0 ] &0x7fULL ; -CPUState *cs =CPU (s390_env_get_cpu (env));uint8_t subfunc[16 ] = {0 };uint64_t param_addr;int i;
@@ -35,8 +34,7 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,case S390_FEAT_TYPE_PCKMO :case S390_FEAT_TYPE_PCC :if (mod) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra);return 0 ; }break ;
@@ -44,8 +42,7 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,s390_get_feat_block (type, subfunc);if (!test_be_bit (fc, subfunc)) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra);return 0 ; }
target/s390x/excp_helper.c +1 -4
@@ -554,10 +554,7 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,S390CPU *cpu =S390_CPU (cs);CPUS390XState *env = &cpu->env; -if (retaddr) { -cpu_restore_state (cs, retaddr); - } - program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); + s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, retaddr); }#endif /* CONFIG_USER_ONLY */
target/s390x/interrupt.c +13 -0
@@ -53,6 +53,19 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) } } +void s390_program_interrupt (CPUS390XState *env,uint32_t code,int ilen, +uintptr_t ra) +{ +#ifdef CONFIG_TCG +S390CPU *cpu =s390_env_get_cpu (env); + +if (tcg_enabled ()) { +cpu_restore_state (CPU (cpu), ra); + } +#endif +program_interrupt (env, code, ilen); +} +#if !defined(CONFIG_USER_ONLY )static void cpu_inject_service (S390CPU *cpu,uint32_t param) {
target/s390x/mem_helper.c +11 -24
@@ -85,9 +85,7 @@ static inline void check_alignment(CPUS390XState *env, uint64_t v, int wordsize, uintptr_t ra) {if (v % wordsize) { -CPUState *cs =CPU (s390_env_get_cpu (env)); -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra); } }
@@ -545,8 +543,7 @@ void HELPER(srst)(CPUS390XState *env, uint32_t r1, uint32_t r2)/* Bits 32-55 must contain all 0. */ if (env->regs[0 ] &0xffffff00u ) { -cpu_restore_state (ENV_GET_CPU (env), ra); -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra); } str =get_address (env, r2);
@@ -583,8 +580,7 @@ void HELPER(srstu)(CPUS390XState *env, uint32_t r1, uint32_t r2)/* Bits 32-47 of R0 must be zero. */ if (env->regs[0 ] &0xffff0000u ) { -cpu_restore_state (ENV_GET_CPU (env), ra); -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra); } str =get_address (env, r2);
@@ -1600,8 +1596,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,return cc; spec_exception: -cpu_restore_state (ENV_GET_CPU (env), ra); -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra);g_assert_not_reached (); }
@@ -1865,8 +1860,7 @@ void HELPER(idte)(CPUS390XState *env, uint64_t r1, uint64_t r2, uint32_t m4)uint16_t entries, i, index =0 ;if (r2 &0xff000 ) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra); }if (!(r2 &0x800 )) {
@@ -2014,8 +2008,7 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)/* XXX incomplete - has more corner cases */ if (!(env->psw.mask &PSW_MASK_64 ) && (addr >>32 )) { -cpu_restore_state (cs,GETPC ()); -program_interrupt (env,PGM_SPECIAL_OP ,2 ); +s390_program_interrupt (env,PGM_SPECIAL_OP ,2 ,GETPC ()); } old_exc = cs->exception_index;
@@ -2185,7 +2178,6 @@ uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src,const uint8_t psw_as = (env->psw.mask &PSW_MASK_ASC ) >>PSW_SHIFT_ASC ;const uint64_t r0 = env->regs[0 ];const uintptr_t ra =GETPC (); -CPUState *cs =CPU (s390_env_get_cpu (env));uint8_t dest_key, dest_as, dest_k, dest_a;uint8_t src_key, src_as, src_k, src_a;uint64_t val;
@@ -2195,8 +2187,7 @@ uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src, __func__, dest, src, len);if (!(env->psw.mask &PSW_MASK_DAT )) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIAL_OP ,6 ); +s390_program_interrupt (env,PGM_SPECIAL_OP ,6 , ra); }/* OAC (operand access control) for the first operand -> dest */
@@ -2227,17 +2218,14 @@ uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src, }if (dest_a && dest_as ==AS_HOME && (env->psw.mask &PSW_MASK_PSTATE )) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIAL_OP ,6 ); +s390_program_interrupt (env,PGM_SPECIAL_OP ,6 , ra); }if (!(env->cregs[0 ] &CR0_SECONDARY ) && (dest_as ==AS_SECONDARY || src_as ==AS_SECONDARY )) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_SPECIAL_OP ,6 ); +s390_program_interrupt (env,PGM_SPECIAL_OP ,6 , ra); }if (!psw_key_valid (env, dest_key) || !psw_key_valid (env, src_key)) { -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_PRIVILEGED ,6 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,6 , ra); } len =wrap_length (env, len);
@@ -2251,8 +2239,7 @@ uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src, (env->psw.mask & PSW_MASK_PSTATE)) {qemu_log_mask (LOG_UNIMP ,"%s: AR-mode and PSTATE support missing\n" , __func__); -cpu_restore_state (cs, ra); -program_interrupt (env,PGM_ADDRESSING ,6 ); +s390_program_interrupt (env,PGM_ADDRESSING ,6 , ra); }/* FIXME: a) LAP
target/s390x/misc_helper.c +1 -2
@@ -519,8 +519,7 @@ uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr)int i;if (addr &0x7 ) { -cpu_restore_state (ENV_GET_CPU (env), ra); -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra); }prepare_stfl ();
Signature · 1 line
2.14.3
PATCH v3 2/16 s390x/tcg: get rid of runtime_exception()
In reply to David HildenbrandLet's use s390_program_interrupt() instead.
--- target/s390x/fpu_helper.c | 2 +- target/s390x/int_helper.c | 14 +++++++------- target/s390x/internal.h | 2 -- target/s390x/misc_helper.c | 16 ---------------- 4 files changed, 8 insertions(+), 26 deletions(-)
target/s390x/fpu_helper.c +1 -1
@@ -44,7 +44,7 @@ static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)/* Install the DXC code. */ env->fpc = (env->fpc & ~0xff00 ) | (dxc <<8 );/* Trap. */ -runtime_exception (env,PGM_DATA , retaddr); +s390_program_interrupt (env,PGM_DATA ,ILEN_AUTO , retaddr); }/* Should be called after any operation that may raise IEEE exceptions. */
target/s390x/int_helper.c +7 -7
@@ -39,7 +39,7 @@ int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)int64_t q;if (b ==0 ) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); } ret = q = a / b;
@@ -47,7 +47,7 @@ int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)/* Catch non-representable quotient. */ if (ret != q) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); }return ret;
@@ -60,7 +60,7 @@ uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)uint64_t q;if (b ==0 ) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); } ret = q = a / b;
@@ -68,7 +68,7 @@ uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)/* Catch non-representable quotient. */ if (ret != q) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); }return ret;
@@ -79,7 +79,7 @@ int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b) {/* Catch divide by zero, and non-representable quotient (MIN / -1). */ if (b ==0 || (b ==-1 && a == (1ll <<63 ))) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); } env->retxl = a % b;return a / b;
@@ -92,7 +92,7 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,uint64_t ret;/* Signal divide by zero. */ if (b ==0 ) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); }if (ah ==0 ) {/* 64 -> 64/64 case */
@@ -106,7 +106,7 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, env->retxl = a % b; ret = q;if (ret != q) { -runtime_exception (env,PGM_FIXPT_DIVIDE ,GETPC ()); +s390_program_interrupt (env,PGM_FIXPT_DIVIDE ,ILEN_AUTO ,GETPC ()); }#else S390CPU *cpu =s390_env_get_cpu (env);
target/s390x/internal.h +0 -2
@@ -408,8 +408,6 @@ int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,/* misc_helper.c */ -void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, -uintptr_t retaddr);int handle_diag_288 (CPUS390XState *env,uint64_t r1,uint64_t r3);void handle_diag_308 (CPUS390XState *env,uint64_t r1,uint64_t r3);
target/s390x/misc_helper.c +0 -16
@@ -45,22 +45,6 @@ #define HELPER_LOG(x...)#endif -/* Raise an exception dynamically from a helper function. */ -void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, -uintptr_t retaddr) -{ -CPUState *cs =CPU (s390_env_get_cpu (env)); - - cs->exception_index =EXCP_PGM ; - env->int_pgm_code = excp; - env->int_pgm_ilen =ILEN_AUTO ; - -/* Use the (ultimate) callers address to find the insn that trapped. */ -cpu_restore_state (cs, retaddr); - -cpu_loop_exit (cs); -} -/* Raise an exception statically from a TB. */ void HELPER (exception )(CPUS390XState *env,uint32_t excp) {
Signature · 1 line
2.14.3
PATCH v3 3/16 s390x/tcg: rip out dead tpi code
In reply to David HildenbrandIt is broken and not even wired up. We'll add a new handler soon, but that will live somewhere else.
--- hw/s390x/css.c | 6 ------ include/hw/s390x/css.h | 1 - target/s390x/internal.h | 1 - target/s390x/ioinst.c | 26 -------------------------- 4 files changed, 34 deletions(-)
hw/s390x/css.c +0 -6
@@ -1723,12 +1723,6 @@ void css_undo_stcrw(CRW *crw)QTAILQ_INSERT_HEAD (&channel_subsys.pending_crws, crw_cont, sibling); } -int css_do_tpi (IOIntCode *int_code,int lowcore) -{ -/* No pending interrupts for !KVM. */ -return 0 ; - } -int css_collect_chp_desc (int m,uint8_t cssid,uint8_t f_chpid,uint8_t l_chpid,int rfmt,void *buf) {
include/hw/s390x/css.h +0 -1
@@ -248,7 +248,6 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *irb, int *irb_len);void css_do_tsch_update_subch (SubchDev *sch);int css_do_stcrw (CRW *crw);void css_undo_stcrw (CRW *crw); -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);
target/s390x/internal.h +0 -1
@@ -388,7 +388,6 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);void ioinst_handle_stsch (S390CPU *cpu,uint64_t reg1,uint32_t ipb);int ioinst_handle_tsch (S390CPU *cpu,uint64_t reg1,uint32_t ipb);void ioinst_handle_chsc (S390CPU *cpu,uint32_t ipb); -int ioinst_handle_tpi (S390CPU *cpu,uint32_t ipb);void ioinst_handle_schm (S390CPU *cpu,uint64_t reg1,uint64_t reg2,uint32_t ipb);void ioinst_handle_rsch (S390CPU *cpu,uint64_t reg1);
target/s390x/ioinst.c +0 -26
@@ -647,32 +647,6 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb) } } -int ioinst_handle_tpi (S390CPU *cpu,uint32_t ipb) -{ -CPUS390XState *env = &cpu->env; -uint64_t addr; -int lowcore; -IOIntCode int_code; -hwaddr len; -int ret; -uint8_t ar; - -trace_ioinst ("tpi" ); - addr =decode_basedisp_s (env, ipb, &ar); -if (addr &3 ) { -program_interrupt (env,PGM_SPECIFICATION ,4 ); -return -EIO ; - } - - lowcore = addr ?0 :1 ; - len = lowcore ?8 /* two words */ :12 /* three words */ ; - ret =css_do_tpi (&int_code, lowcore); -if (ret ==1 ) { -s390_cpu_virt_mem_write (cpu, lowcore ?184 : addr, ar, &int_code, len); - } -return ret; -} -#define SCHM_REG1_RES (_reg) (_reg & 0x000000000ffffffc)#define SCHM_REG1_MBK (_reg) ((_reg & 0x00000000f0000000) >> 28)#define SCHM_REG1_UPD (_reg) ((_reg & 0x0000000000000002) >> 1)
Signature · 1 line
2.14.3
PATCH v3 4/16 s390x/ioinst: pass the retaddr to all IO instructions
In reply to David HildenbrandTCG needs the retaddr when injecting an interrupt. Let's just pass it along and use RA_IGNORED for KVM. The value will be completely ignored for KVM.
Convert program_interrupt() to s390_program_interrupt() directly, making use of the passed address.
--- target/s390x/cpu.h | 1 + target/s390x/internal.h | 29 +++++++++++--------- target/s390x/ioinst.c | 67 +++++++++++++++++++++++----------------------- target/s390x/kvm.c | 27 ++++++++++--------- target/s390x/misc_helper.c | 20 +++++++------- 5 files changed, 75 insertions(+), 69 deletions(-)
target/s390x/cpu.h +1 -0
@@ -720,6 +720,7 @@ void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,/* automatically detect the instruction length */ #define ILEN_AUTO 0xffvoid program_interrupt (CPUS390XState *env,uint32_t code,int ilen); +#define RA_IGNORED 0void s390_program_interrupt (CPUS390XState *env,uint32_t code,int ilen,uintptr_t ra);/* service interrupts are floating therefore we must not pass an cpustate */
target/s390x/internal.h +16 -13
@@ -379,20 +379,23 @@ void cpu_inject_stop(S390CPU *cpu);/* ioinst.c */ -void ioinst_handle_xsch (S390CPU *cpu,uint64_t reg1); -void ioinst_handle_csch (S390CPU *cpu,uint64_t reg1); -void ioinst_handle_hsch (S390CPU *cpu,uint64_t reg1); -void ioinst_handle_msch (S390CPU *cpu,uint64_t reg1,uint32_t ipb); -void ioinst_handle_ssch (S390CPU *cpu,uint64_t reg1,uint32_t ipb); -void ioinst_handle_stcrw (S390CPU *cpu,uint32_t ipb); -void ioinst_handle_stsch (S390CPU *cpu,uint64_t reg1,uint32_t ipb); -int ioinst_handle_tsch (S390CPU *cpu,uint64_t reg1,uint32_t ipb); -void ioinst_handle_chsc (S390CPU *cpu,uint32_t ipb); +void ioinst_handle_xsch (S390CPU *cpu,uint64_t reg1,uintptr_t ra); +void ioinst_handle_csch (S390CPU *cpu,uint64_t reg1,uintptr_t ra); +void ioinst_handle_hsch (S390CPU *cpu,uint64_t reg1,uintptr_t ra); +void ioinst_handle_msch (S390CPU *cpu,uint64_t reg1,uint32_t ipb, +uintptr_t ra); +void ioinst_handle_ssch (S390CPU *cpu,uint64_t reg1,uint32_t ipb, +uintptr_t ra); +void ioinst_handle_stcrw (S390CPU *cpu,uint32_t ipb,uintptr_t ra); +void ioinst_handle_stsch (S390CPU *cpu,uint64_t reg1,uint32_t ipb, +uintptr_t ra); +int ioinst_handle_tsch (S390CPU *cpu,uint64_t reg1,uint32_t ipb,uintptr_t ra); +void ioinst_handle_chsc (S390CPU *cpu,uint32_t ipb,uintptr_t ra);void ioinst_handle_schm (S390CPU *cpu,uint64_t reg1,uint64_t reg2, -uint32_t ipb); -void ioinst_handle_rsch (S390CPU *cpu,uint64_t reg1); -void ioinst_handle_rchp (S390CPU *cpu,uint64_t reg1); -void ioinst_handle_sal (S390CPU *cpu,uint64_t reg1); +uint32_t ipb,uintptr_t ra); +void ioinst_handle_rsch (S390CPU *cpu,uint64_t reg1,uintptr_t ra); +void ioinst_handle_rchp (S390CPU *cpu,uint64_t reg1,uintptr_t ra); +void ioinst_handle_sal (S390CPU *cpu,uint64_t reg1,uintptr_t ra);/* mem_helper.c */
target/s390x/ioinst.c +34 -33
256 lines not on this page · raw message
target/s390x/kvm.c +14 -13
@@ -1124,32 +1124,32 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)switch (ipa1) {case PRIV_B2_XSCH : -ioinst_handle_xsch (cpu, env->regs[1 ]); +ioinst_handle_xsch (cpu, env->regs[1 ],RA_IGNORED );break ;case PRIV_B2_CSCH : -ioinst_handle_csch (cpu, env->regs[1 ]); +ioinst_handle_csch (cpu, env->regs[1 ],RA_IGNORED );break ;case PRIV_B2_HSCH : -ioinst_handle_hsch (cpu, env->regs[1 ]); +ioinst_handle_hsch (cpu, env->regs[1 ],RA_IGNORED );break ;case PRIV_B2_MSCH : -ioinst_handle_msch (cpu, env->regs[1 ], run->s390_sieic.ipb); +ioinst_handle_msch (cpu, env->regs[1 ], run->s390_sieic.ipb,RA_IGNORED );break ;case PRIV_B2_SSCH : -ioinst_handle_ssch (cpu, env->regs[1 ], run->s390_sieic.ipb); +ioinst_handle_ssch (cpu, env->regs[1 ], run->s390_sieic.ipb,RA_IGNORED );break ;case PRIV_B2_STCRW : -ioinst_handle_stcrw (cpu, run->s390_sieic.ipb); +ioinst_handle_stcrw (cpu, run->s390_sieic.ipb,RA_IGNORED );break ;case PRIV_B2_STSCH : -ioinst_handle_stsch (cpu, env->regs[1 ], run->s390_sieic.ipb); +ioinst_handle_stsch (cpu, env->regs[1 ], run->s390_sieic.ipb,RA_IGNORED );break ;case PRIV_B2_TSCH :/* We should only get tsch via KVM_EXIT_S390_TSCH. */ fprintf (stderr,"Spurious tsch intercept\n" );break ;case PRIV_B2_CHSC : -ioinst_handle_chsc (cpu, run->s390_sieic.ipb); +ioinst_handle_chsc (cpu, run->s390_sieic.ipb,RA_IGNORED );break ;case PRIV_B2_TPI :/* This should have been handled by kvm already. */
@@ -1157,19 +1157,19 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)break ;case PRIV_B2_SCHM :ioinst_handle_schm (cpu, env->regs[1 ], env->regs[2 ], - run->s390_sieic.ipb); + run->s390_sieic.ipb,RA_IGNORED );break ;case PRIV_B2_RSCH : -ioinst_handle_rsch (cpu, env->regs[1 ]); +ioinst_handle_rsch (cpu, env->regs[1 ],RA_IGNORED );break ;case PRIV_B2_RCHP : -ioinst_handle_rchp (cpu, env->regs[1 ]); +ioinst_handle_rchp (cpu, env->regs[1 ],RA_IGNORED );break ;case PRIV_B2_STCPS :/* We do not provide this instruction, it is suppressed. */ break ;case PRIV_B2_SAL : -ioinst_handle_sal (cpu, env->regs[1 ]); +ioinst_handle_sal (cpu, env->regs[1 ],RA_IGNORED );break ;case PRIV_B2_SIGA :/* Not provided, set CC = 3 for subchannel not operational */
@@ -1673,7 +1673,8 @@ static int handle_tsch(S390CPU *cpu)cpu_synchronize_state (cs); - ret =ioinst_handle_tsch (cpu, cpu->env.regs[1 ], run->s390_tsch.ipb); + ret =ioinst_handle_tsch (cpu, cpu->env.regs[1 ], run->s390_tsch.ipb, +RA_IGNORED );if (ret <0 ) {/* * Failure.
target/s390x/misc_helper.c +10 -10
@@ -323,7 +323,7 @@ void HELPER(xsch)(CPUS390XState *env, uint64_t r1) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_xsch (cpu, r1); +ioinst_handle_xsch (cpu, r1,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -331,7 +331,7 @@ void HELPER(csch)(CPUS390XState *env, uint64_t r1) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_csch (cpu, r1); +ioinst_handle_csch (cpu, r1,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -339,7 +339,7 @@ void HELPER(hsch)(CPUS390XState *env, uint64_t r1) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_hsch (cpu, r1); +ioinst_handle_hsch (cpu, r1,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -347,7 +347,7 @@ void HELPER(msch)(CPUS390XState *env, uint64_t r1, uint64_t inst) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_msch (cpu, r1, inst >>16 ); +ioinst_handle_msch (cpu, r1, inst >>16 ,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -355,7 +355,7 @@ void HELPER(rchp)(CPUS390XState *env, uint64_t r1) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_rchp (cpu, r1); +ioinst_handle_rchp (cpu, r1,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -363,7 +363,7 @@ void HELPER(rsch)(CPUS390XState *env, uint64_t r1) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_rsch (cpu, r1); +ioinst_handle_rsch (cpu, r1,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -371,7 +371,7 @@ void HELPER(ssch)(CPUS390XState *env, uint64_t r1, uint64_t inst) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_ssch (cpu, r1, inst >>16 ); +ioinst_handle_ssch (cpu, r1, inst >>16 ,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -379,7 +379,7 @@ void HELPER(stsch)(CPUS390XState *env, uint64_t r1, uint64_t inst) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_stsch (cpu, r1, inst >>16 ); +ioinst_handle_stsch (cpu, r1, inst >>16 ,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -387,7 +387,7 @@ void HELPER(tsch)(CPUS390XState *env, uint64_t r1, uint64_t inst) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_tsch (cpu, r1, inst >>16 ); +ioinst_handle_tsch (cpu, r1, inst >>16 ,GETPC ());qemu_mutex_unlock_iothread (); }
@@ -395,7 +395,7 @@ void HELPER(chsc)(CPUS390XState *env, uint64_t inst) {S390CPU *cpu =s390_env_get_cpu (env);qemu_mutex_lock_iothread (); -ioinst_handle_chsc (cpu, inst >>16 ); +ioinst_handle_chsc (cpu, inst >>16 ,GETPC ());qemu_mutex_unlock_iothread (); }#endif
Signature · 1 line
2.14.3
PATCH v3 5/16 s390x/pci: pass the retaddr to all PCI instructions
In reply to David HildenbrandOnce we wire up TCG, we will need the retaddr to correctly inject program interrupts. As we want to get rid of the function program_interrupt(), convert PCI code too.
For KVM, we can simply use RA_IGNORED.
Convert program_interrupt() to s390_program_interrupt() directly, making use of the passed address.
--- hw/s390x/s390-pci-inst.c | 83 +++++++++++++++++++++++++----------------------- hw/s390x/s390-pci-inst.h | 16 ++++++---- target/s390x/kvm.c | 14 ++++---- 3 files changed, 59 insertions(+), 54 deletions(-)
hw/s390x/s390-pci-inst.c +43 -40
@@ -142,7 +142,7 @@ out:return rc; } -int clp_service_call (S390CPU *cpu,uint8_t r2) +int clp_service_call (S390CPU *cpu,uint8_t r2,uintptr_t ra) {ClpReqHdr *reqh;ClpRspHdr *resh;
@@ -158,7 +158,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)cpu_synchronize_state (CPU (cpu));if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,4 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,4 , ra);return 0 ; }
@@ -168,7 +168,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) reqh = (ClpReqHdr *)buffer; req_len =lduw_p (&reqh->len);if (req_len <16 || req_len >8184 || (req_len %8 !=0 )) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; }
@@ -179,11 +179,11 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) resh = (ClpRspHdr *)(buffer + req_len); res_len =lduw_p (&resh->len);if (res_len <8 || res_len >8176 || (res_len %8 !=0 )) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; }if ((req_len + res_len) >8192 ) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; }
@@ -314,7 +314,7 @@ out:return 0 ; } -int pcilg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2) +int pcilg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2,uintptr_t ra) {CPUS390XState *env = &cpu->env;S390PCIBusDevice *pbdev;
@@ -329,12 +329,12 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)cpu_synchronize_state (CPU (cpu));if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,4 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,4 , ra);return 0 ; }if (r2 &0x1 ) { -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra);return 0 ; }
@@ -367,19 +367,19 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)if (pcias <6 ) {if ((8 - (offset &0x7 )) < len) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; } mr = pbdev->pdev->io_regions[pcias].memory; result =memory_region_dispatch_read (mr, offset, &data, len,MEMTXATTRS_UNSPECIFIED );if (result !=MEMTX_OK ) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; } }else if (pcias ==15 ) {if ((4 - (offset &0x3 )) < len) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; } data = pci_host_config_read_common(
@@ -398,7 +398,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) data =bswap64 (data);break ;default : -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; } }else {
@@ -425,7 +425,7 @@ static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias) } } -int pcistg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2) +int pcistg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2,uintptr_t ra) {CPUS390XState *env = &cpu->env;uint64_t offset, data;
@@ -439,12 +439,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)cpu_synchronize_state (CPU (cpu));if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,4 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,4 , ra);return 0 ; }if (r2 &0x1 ) { -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra);return 0 ; }
@@ -478,7 +478,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) data = env->regs[r1];if (pcias <6 ) {if ((8 - (offset &0x7 )) < len) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; }
@@ -492,12 +492,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) result =memory_region_dispatch_write (mr, offset, data, len,MEMTXATTRS_UNSPECIFIED );if (result !=MEMTX_OK ) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; } }else if (pcias ==15 ) {if ((4 - (offset &0x3 )) < len) { -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; }switch (len) {
@@ -513,7 +513,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) data =bswap64 (data);break ;default : -program_interrupt (env,PGM_OPERAND ,4 ); +s390_program_interrupt (env,PGM_OPERAND ,4 , ra);return 0 ; }
@@ -531,7 +531,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)return 0 ; } -int rpcit_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2) +int rpcit_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2,uintptr_t ra) {CPUS390XState *env = &cpu->env;uint32_t fh;
@@ -545,12 +545,12 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)cpu_synchronize_state (CPU (cpu));if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,4 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,4 , ra); goto out; }if (r2 &0x1 ) { -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 , ra); goto out; }
@@ -624,7 +624,7 @@ out: }int pcistb_service_call (S390CPU *cpu,uint8_t r1,uint8_t r3,uint64_t gaddr, -uint8_t ar) +uint8_t ar,uintptr_t ra) {CPUS390XState *env = &cpu->env;S390PCIBusDevice *pbdev;
@@ -637,7 +637,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,uint8_t buffer[128 ];if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,6 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,6 , ra);return 0 ; }
@@ -659,7 +659,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,case 128 :break ;default : -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra);return 0 ; }
@@ -687,7 +687,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, mr = pbdev->pdev->io_regions[pcias].memory;if (!memory_region_access_valid (mr, env->regs[r3], len, true)) { -program_interrupt (env,PGM_OPERAND ,6 ); +s390_program_interrupt (env,PGM_OPERAND ,6 , ra);return 0 ; }
@@ -700,7 +700,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,ldq_p (buffer + i *8 ),8 , MEMTXATTRS_UNSPECIFIED);if (result !=MEMTX_OK ) { -program_interrupt (env,PGM_OPERAND ,6 ); +s390_program_interrupt (env,PGM_OPERAND ,6 , ra);return 0 ; } }
@@ -767,7 +767,8 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev)return 0 ; } -static int reg_ioat (CPUS390XState *env,S390PCIIOMMU *iommu,ZpciFib fib) +static int reg_ioat (CPUS390XState *env,S390PCIIOMMU *iommu,ZpciFib fib, +uintptr_t ra) {uint64_t pba =ldq_p (&fib.pba);uint64_t pal =ldq_p (&fib.pal);
@@ -776,14 +777,14 @@ static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib)uint8_t t = (g_iota >>11 ) &0x1 ;if (pba > pal || pba <ZPCI_SDMA_ADDR || pal >ZPCI_EDMA_ADDR ) { -program_interrupt (env,PGM_OPERAND ,6 ); +s390_program_interrupt (env,PGM_OPERAND ,6 , ra);return -EINVAL ; }/* currently we only support designation type 1 with translation */ if (!(dt ==ZPCI_IOTA_RTTO && t)) {error_report ("unsupported ioat dt %d t %d" , dt, t); -program_interrupt (env,PGM_OPERAND ,6 ); +s390_program_interrupt (env,PGM_OPERAND ,6 , ra);return -EINVAL ; }
@@ -804,7 +805,8 @@ void pci_dereg_ioat(S390PCIIOMMU *iommu) iommu->g_iota =0 ; } -int mpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar) +int mpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar, +uintptr_t ra) {CPUS390XState *env = &cpu->env;uint8_t oc, dmaas;
@@ -814,7 +816,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)uint64_t cc =ZPCI_PCI_LS_OK ;if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,6 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,6 , ra);return 0 ; }
@@ -823,7 +825,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) fh = env->regs[r1] >>32 ;if (fiba &0x7 ) { -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra);return 0 ; }
@@ -850,7 +852,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) }if (fib.fmt !=0 ) { -program_interrupt (env,PGM_OPERAND ,6 ); +s390_program_interrupt (env,PGM_OPERAND ,6 , ra);return 0 ; }
@@ -879,7 +881,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) }else if (pbdev->iommu->enabled) { cc =ZPCI_PCI_LS_ERR ;s390_set_status_code (env, r1,ZPCI_MOD_ST_SEQUENCE ); - }else if (reg_ioat (env, pbdev->iommu, fib)) { + }else if (reg_ioat (env, pbdev->iommu, fib, ra)) { cc =ZPCI_PCI_LS_ERR ;s390_set_status_code (env, r1,ZPCI_MOD_ST_INSUF_RES ); }
@@ -904,7 +906,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)s390_set_status_code (env, r1,ZPCI_MOD_ST_SEQUENCE ); }else {pci_dereg_ioat (pbdev->iommu); -if (reg_ioat (env, pbdev->iommu, fib)) { +if (reg_ioat (env, pbdev->iommu, fib, ra)) { cc =ZPCI_PCI_LS_ERR ;s390_set_status_code (env, r1,ZPCI_MOD_ST_INSUF_RES ); }
@@ -935,7 +937,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) pbdev->fmb_addr =ldq_p (&fib.fmb_addr);break ;default : -program_interrupt (&cpu->env,PGM_OPERAND ,6 ); +s390_program_interrupt (&cpu->env,PGM_OPERAND ,6 , ra); cc =ZPCI_PCI_LS_ERR ; }
@@ -943,7 +945,8 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)return 0 ; } -int stpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar) +int stpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar, +uintptr_t ra) {CPUS390XState *env = &cpu->env;uint8_t dmaas;
@@ -954,7 +957,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)uint64_t cc =ZPCI_PCI_LS_OK ;if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,6 ); +s390_program_interrupt (env,PGM_PRIVILEGED ,6 , ra);return 0 ; }
@@ -968,7 +971,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) }if (fiba &0x7 ) { -program_interrupt (env,PGM_SPECIFICATION ,6 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,6 , ra);return 0 ; }
hw/s390x/s390-pci-inst.h +9 -7
@@ -293,13 +293,15 @@ typedef struct ZpciFib {int pci_dereg_irqs (S390PCIBusDevice *pbdev);void pci_dereg_ioat (S390PCIIOMMU *iommu); -int clp_service_call (S390CPU *cpu,uint8_t r2); -int pcilg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2); -int pcistg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2); -int rpcit_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2); +int clp_service_call (S390CPU *cpu,uint8_t r2,uintptr_t ra); +int pcilg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2,uintptr_t ra); +int pcistg_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2,uintptr_t ra); +int rpcit_service_call (S390CPU *cpu,uint8_t r1,uint8_t r2,uintptr_t ra);int pcistb_service_call (S390CPU *cpu,uint8_t r1,uint8_t r3,uint64_t gaddr, -uint8_t ar); -int mpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar); -int stpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar); +uint8_t ar,uintptr_t ra); +int mpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar, +uintptr_t ra); +int stpcifc_service_call (S390CPU *cpu,uint8_t r1,uint64_t fiba,uint8_t ar, +uintptr_t ra);#endif
target/s390x/kvm.c +7 -7
@@ -1230,7 +1230,7 @@ static int kvm_clp_service_call(S390CPU *cpu, struct kvm_run *run)uint8_t r2 = (run->s390_sieic.ipb &0x000f0000 ) >>16 ;if (s390_has_feat (S390_FEAT_ZPCI )) { -return clp_service_call (cpu, r2); +return clp_service_call (cpu, r2,RA_IGNORED ); }else {return -1 ; }
@@ -1242,7 +1242,7 @@ static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run)uint8_t r2 = (run->s390_sieic.ipb &0x000f0000 ) >>16 ;if (s390_has_feat (S390_FEAT_ZPCI )) { -return pcilg_service_call (cpu, r1, r2); +return pcilg_service_call (cpu, r1, r2,RA_IGNORED ); }else {return -1 ; }
@@ -1254,7 +1254,7 @@ static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run)uint8_t r2 = (run->s390_sieic.ipb &0x000f0000 ) >>16 ;if (s390_has_feat (S390_FEAT_ZPCI )) { -return pcistg_service_call (cpu, r1, r2); +return pcistg_service_call (cpu, r1, r2,RA_IGNORED ); }else {return -1 ; }
@@ -1270,7 +1270,7 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)cpu_synchronize_state (CPU (cpu)); fiba =get_base_disp_rxy (cpu, run, &ar); -return stpcifc_service_call (cpu, r1, fiba, ar); +return stpcifc_service_call (cpu, r1, fiba, ar,RA_IGNORED ); }else {return -1 ; }
@@ -1302,7 +1302,7 @@ static int kvm_rpcit_service_call(S390CPU *cpu, struct kvm_run *run)uint8_t r2 = (run->s390_sieic.ipb &0x000f0000 ) >>16 ;if (s390_has_feat (S390_FEAT_ZPCI )) { -return rpcit_service_call (cpu, r1, r2); +return rpcit_service_call (cpu, r1, r2,RA_IGNORED ); }else {return -1 ; }
@@ -1319,7 +1319,7 @@ static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)cpu_synchronize_state (CPU (cpu)); gaddr =get_base_disp_rsy (cpu, run, &ar); -return pcistb_service_call (cpu, r1, r3, gaddr, ar); +return pcistb_service_call (cpu, r1, r3, gaddr, ar,RA_IGNORED ); }else {return -1 ; }
@@ -1335,7 +1335,7 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)cpu_synchronize_state (CPU (cpu)); fiba =get_base_disp_rxy (cpu, run, &ar); -return mpcifc_service_call (cpu, r1, fiba, ar); +return mpcifc_service_call (cpu, r1, fiba, ar,RA_IGNORED ); }else {return -1 ; }
Signature · 1 line
2.14.3
PATCH v3 6/16 s390x/diag: pass the retaddr into handle_diag_308()
In reply to David HildenbrandNeeded to later drop potential_page_fault() from the diag TCG translate function.
Convert program_interrupt() to s390_program_interrupt() directly, making use of the passed address.
--- target/s390x/diag.c | 14 +++++++------- target/s390x/internal.h | 3 ++- target/s390x/kvm.c | 2 +- target/s390x/misc_helper.c | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-)
target/s390x/diag.c +7 -7
@@ -99,19 +99,19 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3)#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) +void handle_diag_308 (CPUS390XState *env,uint64_t r1,uint64_t r3,uintptr_t ra) {uint64_t addr = env->regs[r1];uint64_t subcode = env->regs[r3];IplParameterBlock *iplb;if (env->psw.mask &PSW_MASK_PSTATE ) { -program_interrupt (env,PGM_PRIVILEGED ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_PRIVILEGED ,ILEN_AUTO , ra);return ; }if ((subcode & ~0x0ffffULL ) || (subcode >6 )) { -program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO , ra);return ; }
@@ -136,12 +136,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)break ;case 5 :if ((r1 &1 ) || (addr &0x0fffULL )) { -program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO , ra);return ; }if (!address_space_access_valid (&address_space_memory, addr,sizeof (IplParameterBlock), false)) { -program_interrupt (env,PGM_ADDRESSING ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_ADDRESSING ,ILEN_AUTO , ra);return ; } iplb =g_new0 (IplParameterBlock,1 );
@@ -165,12 +165,12 @@ out:return ;case 6 :if ((r1 &1 ) || (addr &0x0fffULL )) { -program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO , ra);return ; }if (!address_space_access_valid (&address_space_memory, addr,sizeof (IplParameterBlock), true)) { -program_interrupt (env,PGM_ADDRESSING ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_ADDRESSING ,ILEN_AUTO , ra);return ; } iplb =s390_ipl_get_iplb ();
target/s390x/internal.h +2 -1
@@ -411,7 +411,8 @@ int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,/* misc_helper.c */ 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, +uintptr_t ra);/* translate.c */
target/s390x/kvm.c +1 -1
@@ -1451,7 +1451,7 @@ static void kvm_handle_diag_308(S390CPU *cpu, struct kvm_run *run)cpu_synchronize_state (CPU (cpu)); r1 = (run->s390_sieic.ipa &0x00f0 ) >>4 ; r3 = run->s390_sieic.ipa &0x000f ; -handle_diag_308 (&cpu->env, r1, r3); +handle_diag_308 (&cpu->env, r1, r3,RA_IGNORED ); }static int handle_sw_breakpoint (S390CPU *cpu,struct kvm_run *run)
target/s390x/misc_helper.c +1 -1
@@ -88,7 +88,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)case 0x308 :/* ipl */ qemu_mutex_lock_iothread (); -handle_diag_308 (env, r1, r3); +handle_diag_308 (env, r1, r3,GETPC ());qemu_mutex_unlock_iothread (); r =0 ;break ;
Signature · 1 line
2.14.3
PATCH v3 7/16 s390x: handle exceptions during s390_cpu_virt_mem_rw() correctly (TCG)
In reply to David Hildenbrands390_cpu_virt_mem_rw() must always return, so callers can react on an exception (e.g. see ioinst_handle_stcrw()).
However, for TCG we always have to exit the cpu loop (and restore the cpu state before that) if we injected a program interrupt. So let's introduce and use s390_cpu_virt_mem_handle_exc() in code that is not purely KVM.
Directly pass the retaddr we already have available in these functions.
--- hw/s390x/s390-pci-inst.c | 7 +++++++ target/s390x/cpu.h | 1 + target/s390x/ioinst.c | 20 +++++++++++++++++--- target/s390x/mmu_helper.c | 14 ++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-)
hw/s390x/s390-pci-inst.c +7 -0
@@ -163,6 +163,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) }if (s390_cpu_virt_mem_read (cpu, env->regs[r2], r2, buffer,sizeof (*reqh))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; } reqh = (ClpReqHdr *)buffer;
@@ -174,6 +175,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)if (s390_cpu_virt_mem_read (cpu, env->regs[r2], r2, buffer, req_len +sizeof (*resh))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; } resh = (ClpRspHdr *)(buffer + req_len);
@@ -189,6 +191,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)if (s390_cpu_virt_mem_read (cpu, env->regs[r2], r2, buffer, req_len + res_len)) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; }
@@ -308,6 +311,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) out:if (s390_cpu_virt_mem_write (cpu, env->regs[r2], r2, buffer, req_len + res_len)) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; }setcc (cpu, cc);
@@ -692,6 +696,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, }if (s390_cpu_virt_mem_read (cpu, gaddr, ar, buffer, len)) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; }
@@ -848,6 +853,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, }if (s390_cpu_virt_mem_read (cpu, fiba, ar, (uint8_t *)&fib,sizeof (fib))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; }
@@ -1029,6 +1035,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, out:if (s390_cpu_virt_mem_write (cpu, fiba, ar, (uint8_t *)&fib,sizeof (fib))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return 0 ; }
target/s390x/cpu.h +1 -0
@@ -736,6 +736,7 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true)#define s390_cpu_virt_mem_check_write (cpu, laddr, ar, len) \ s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true) +void s390_cpu_virt_mem_handle_exc (S390CPU *cpu,uintptr_t ra);/* sigp.c */
target/s390x/ioinst.c +17 -3
@@ -120,6 +120,7 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)return ; }if (s390_cpu_virt_mem_read (cpu, addr, ar, &schib,sizeof (schib))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return ; } if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
@@ -176,6 +177,7 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)return ; }if (s390_cpu_virt_mem_read (cpu, addr, ar, &orig_orb,sizeof (orb))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return ; }copy_orb_from_guest (&orb, &orig_orb);
@@ -212,9 +214,12 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)if (s390_cpu_virt_mem_write (cpu, addr, ar, &crw,sizeof (crw)) ==0 ) {setcc (cpu, cc); - }else if (cc ==0 ) { -/* Write failed: requeue CRW since STCRW is a suppressing instruction */ -css_undo_stcrw (&crw); + }else { +if (cc ==0 ) { +/* Write failed: requeue CRW since STCRW is suppressing */ +css_undo_stcrw (&crw); + } +s390_cpu_virt_mem_handle_exc (cpu, ra); } }
@@ -243,6 +248,8 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,*/ if (!s390_cpu_virt_mem_check_write (cpu, addr, ar,sizeof (schib))) {s390_program_interrupt (env,PGM_OPERAND ,4 , ra); + }else { +s390_cpu_virt_mem_handle_exc (cpu, ra); }return ; }
@@ -268,11 +275,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,if (cc !=3 ) {if (s390_cpu_virt_mem_write (cpu, addr, ar, &schib,sizeof (schib)) !=0 ) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return ; } }else {/* Access exceptions have a higher priority than cc3 */ if (s390_cpu_virt_mem_check_write (cpu, addr, ar,sizeof (schib)) !=0 ) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return ; } }
@@ -309,6 +318,7 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)/* 0 - status pending, 1 - not status pending, 3 - not operational */ if (cc !=3 ) {if (s390_cpu_virt_mem_write (cpu, addr, ar, &irb, irb_len) !=0 ) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return -EFAULT ; }css_do_tsch_update_subch (sch);
@@ -316,6 +326,7 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) irb_len =sizeof (irb) -sizeof (irb.emw);/* Access exceptions have a higher priority than cc3 */ if (s390_cpu_virt_mem_check_write (cpu, addr, ar, irb_len) !=0 ) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return -EFAULT ; } }
@@ -611,6 +622,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)* care of req->len here first. */ if (s390_cpu_virt_mem_read (cpu, addr, reg, buf,sizeof (ChscReq))) { +s390_cpu_virt_mem_handle_exc (cpu, ra);return ; } req = (ChscReq *)buf;
@@ -645,6 +657,8 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)if (!s390_cpu_virt_mem_write (cpu, addr + len, reg, res,be16_to_cpu (res->len))) {setcc (cpu,0 );/* Command execution complete */ + }else { +s390_cpu_virt_mem_handle_exc (cpu, ra); } }
target/s390x/mmu_helper.c +14 -0
@@ -22,6 +22,7 @@#include "internal.h" #include "kvm_s390x.h" #include "sysemu/kvm.h" +#include "exec/exec-all.h" #include "trace.h" #include "hw/s390x/storage-keys.h"
@@ -478,6 +479,9 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages,* * Copy from/to guest memory using logical addresses. Note that we inject a * program interrupt in case there is an error while accessing the memory. +* +* This function will always return (also for TCG), make sure to call +* s390_cpu_virt_mem_handle_exc() to properly exit the CPU loop. */ int s390_cpu_virt_mem_rw (S390CPU *cpu,vaddr laddr,uint8_t ar,void *hostbuf,int len,bool is_write)
@@ -514,6 +518,16 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,return ret; } +void s390_cpu_virt_mem_handle_exc (S390CPU *cpu,uintptr_t ra) +{ +/* KVM will handle the interrupt automatically, TCG has to exit the TB */ +#ifdef CONFIG_TCG +if (tcg_enabled ()) { +cpu_loop_exit_restore (CPU (cpu), ra); + } +#endif +} +/** * Translate a real address into a physical (absolute) address. * @param raddr the real address
Signature · 1 line
2.14.3
PATCH v3 8/16 s390x/tcg: don't exit the cpu loop in s390_cpu_virt_mem_rw()
In reply to David Hildenbrands390_cpu_virt_mem_rw() must always return, so callers can react on an exception (e.g. see ioinst_handle_stcrw()).
Therefore, using program_interrupt() is wrong. Fix that up.
--- target/s390x/mmu_helper.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
target/s390x/mmu_helper.c +6 -3
@@ -64,7 +64,9 @@ static void trigger_access_exception(CPUS390XState *env, uint32_t type,kvm_s390_access_exception (cpu, type, tec); }else {CPUState *cs =CPU (cpu); -stq_phys (cs->as, env->psa + offsetof(LowCore , trans_exc_code), tec); +if (type !=PGM_ADDRESSING ) { +stq_phys (cs->as, env->psa + offsetof(LowCore , trans_exc_code), tec); + }trigger_pgm_exception (env, type, ilen); } }
@@ -443,7 +445,8 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,/** * translate_pages: Translate a set of consecutive logical page addresses -* to absolute addresses +* to absolute addresses. This function is used for TCG and old KVM without +* the MEMOP interface. */ static int translate_pages (S390CPU *cpu,vaddr addr,int nr_pages,target_ulong *pages,bool is_write)
@@ -459,7 +462,7 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, }if (!address_space_access_valid (&address_space_memory, pages[i],TARGET_PAGE_SIZE , is_write)) { -program_interrupt (env,PGM_ADDRESSING ,ILEN_AUTO ); +trigger_access_exception (env,PGM_ADDRESSING ,ILEN_AUTO ,0 );return -EFAULT ; } addr +=TARGET_PAGE_SIZE ;
Signature · 1 line
2.14.3
PATCH v3 9/16 s390x/tcg: io instructions don't need potential_page_fault()
In reply to David HildenbrandAs we handle the retaddr in all cases properly now, we can drop it.
--- target/s390x/translate.c | 10 ---------- 1 file changed, 10 deletions(-)
target/s390x/translate.c +0 -10
@@ -4008,7 +4008,6 @@ static ExitStatus op_spx(DisasContext *s, DisasOps *o)static ExitStatus op_xsch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_xsch (cpu_env, regs[1 ]);set_cc_static (s);return NO_EXIT ;
@@ -4017,7 +4016,6 @@ static ExitStatus op_xsch(DisasContext *s, DisasOps *o)static ExitStatus op_csch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_csch (cpu_env, regs[1 ]);set_cc_static (s);return NO_EXIT ;
@@ -4026,7 +4024,6 @@ static ExitStatus op_csch(DisasContext *s, DisasOps *o)static ExitStatus op_hsch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_hsch (cpu_env, regs[1 ]);set_cc_static (s);return NO_EXIT ;
@@ -4035,7 +4032,6 @@ static ExitStatus op_hsch(DisasContext *s, DisasOps *o)static ExitStatus op_msch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_msch (cpu_env, regs[1 ], o->in2);set_cc_static (s);return NO_EXIT ;
@@ -4044,7 +4040,6 @@ static ExitStatus op_msch(DisasContext *s, DisasOps *o)static ExitStatus op_rchp (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_rchp (cpu_env, regs[1 ]);set_cc_static (s);return NO_EXIT ;
@@ -4053,7 +4048,6 @@ static ExitStatus op_rchp(DisasContext *s, DisasOps *o)static ExitStatus op_rsch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_rsch (cpu_env, regs[1 ]);set_cc_static (s);return NO_EXIT ;
@@ -4062,7 +4056,6 @@ static ExitStatus op_rsch(DisasContext *s, DisasOps *o)static ExitStatus op_ssch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_ssch (cpu_env, regs[1 ], o->in2);set_cc_static (s);return NO_EXIT ;
@@ -4071,7 +4064,6 @@ static ExitStatus op_ssch(DisasContext *s, DisasOps *o)static ExitStatus op_stsch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_stsch (cpu_env, regs[1 ], o->in2);set_cc_static (s);return NO_EXIT ;
@@ -4080,7 +4072,6 @@ static ExitStatus op_stsch(DisasContext *s, DisasOps *o)static ExitStatus op_tsch (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_tsch (cpu_env, regs[1 ], o->in2);set_cc_static (s);return NO_EXIT ;
@@ -4089,7 +4080,6 @@ static ExitStatus op_tsch(DisasContext *s, DisasOps *o)static ExitStatus op_chsc (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_chsc (cpu_env, o->in2);set_cc_static (s);return NO_EXIT ;
Signature · 1 line
2.14.3
PATCH v3 10/16 s390x/tcg: use s390_program_interrupt() in SCLP Service Call
In reply to David HildenbrandNow we can drop potential_page_fault(). While at it, move the unlock further up, looks cleaner.
--- target/s390x/misc_helper.c | 5 ++--- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 4 deletions(-)
target/s390x/misc_helper.c +2 -3
@@ -62,11 +62,10 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) {qemu_mutex_lock_iothread ();int r =sclp_service_call (env, r1, r2); +qemu_mutex_unlock_iothread ();if (r <0 ) { -program_interrupt (env, -r,4 ); - r =0 ; +s390_program_interrupt (env, -r,4 ,GETPC ()); } -qemu_mutex_unlock_iothread ();return r; }
target/s390x/translate.c +0 -1
@@ -3704,7 +3704,6 @@ static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)static ExitStatus op_servc (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_servc (cc_op, cpu_env, o->in2, o->in1);set_cc_static (s);return NO_EXIT ;
Signature · 1 line
2.14.3
PATCH v3 11/16 s390x/tcg: use s390_program_interrupt() in DIAG
In reply to David HildenbrandNow we can drop the two save statements in the translate function.
--- target/s390x/misc_helper.c | 2 +- target/s390x/translate.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-)
target/s390x/misc_helper.c +1 -1
@@ -101,7 +101,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num) }if (r) { -program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO ); +s390_program_interrupt (env,PGM_SPECIFICATION ,ILEN_AUTO ,GETPC ()); } }
target/s390x/translate.c +0 -3
@@ -2124,9 +2124,6 @@ static ExitStatus op_diag(DisasContext *s, DisasOps *o)TCGv_i32 func_code =tcg_const_i32 (get_field (s->fields, i2));check_privileged (s); -update_psw_addr (s); -gen_op_calc_cc (s); -gen_helper_diag (cpu_env, r1, r3, func_code);tcg_temp_free_i32 (func_code);
Signature · 1 line
2.14.3
PATCH v3 12/16 s390x/tcg: use s390_program_interrupt() in per_check_exception()
In reply to David HildenbrandWe can now drop updating the cc.
--- target/s390x/misc_helper.c | 2 +- target/s390x/translate.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-)
target/s390x/misc_helper.c +1 -1
@@ -412,7 +412,7 @@ void HELPER(per_check_exception)(CPUS390XState *env)* of EXECUTE, while per_address contains the target of EXECUTE. */ ilen =get_ilen (cpu_ldub_code (env, env->per_address)); -program_interrupt (env,PGM_PER , ilen); +s390_program_interrupt (env,PGM_PER , ilen,GETPC ()); } }
target/s390x/translate.c +0 -3
@@ -5837,9 +5837,6 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)tcg_gen_movi_i64 (psw_addr, s->next_pc); } -/* Save off cc. */ -update_cc_op (s); -/* Call the helper to check for a possible PER exception. */ gen_helper_per_check_exception (cpu_env); }
Signature · 1 line
2.14.3
PATCH v3 13/16 s390x/tcg: use s390_program_interrupt() in SACF
In reply to David HildenbrandConvert this user, too.
--- target/s390x/cc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
target/s390x/cc_helper.c +1 -1
@@ -564,7 +564,7 @@ void HELPER(sacf)(CPUS390XState *env, uint64_t a1)break ;default :HELPER_LOG ("unknown sacf mode: %" PRIx64"\n" , a1); -program_interrupt (env,PGM_SPECIFICATION ,2 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,2 ,GETPC ());break ; } }
Signature · 1 line
2.14.3
PATCH v3 14/16 s390x/tcg: use s390_program_interrupt() in STSI
In reply to David HildenbrandSTSI needs some more love, but let's do one step at a time. We can now drop potential_page_fault().
--- target/s390x/misc_helper.c | 2 +- target/s390x/translate.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
target/s390x/misc_helper.c +1 -1
@@ -184,7 +184,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,if ((r0 &STSI_LEVEL_MASK ) <=STSI_LEVEL_3 && ((r0 &STSI_R0_RESERVED_MASK ) || (r1 &STSI_R1_RESERVED_MASK ))) {/* valid function code, invalid reserved bits */ -program_interrupt (env,PGM_SPECIFICATION ,4 ); +s390_program_interrupt (env,PGM_SPECIFICATION ,4 ,GETPC ()); } sel1 = r0 &STSI_R0_SEL1_MASK ;
target/s390x/translate.c +0 -1
@@ -3988,7 +3988,6 @@ static ExitStatus op_stpt(DisasContext *s, DisasOps *o)static ExitStatus op_stsi (DisasContext *s,DisasOps *o) {check_privileged (s); -potential_page_fault (s);gen_helper_stsi (cc_op, cpu_env, o->in2, regs[0 ], regs[1 ]);set_cc_static (s);return NO_EXIT ;
Signature · 1 line
2.14.3
PATCH v3 15/16 s390x/tcg: drop program_interrupt()
In reply to David HildenbrandAll users are gone, we can finally drop it and make sure that all new program interrupt injections are reminded of the retaddr - as they have to use s390_program_interrupt() now.
--- target/s390x/cpu.h | 1 - target/s390x/interrupt.c | 22 +++++----------------- 2 files changed, 5 insertions(+), 18 deletions(-)
target/s390x/cpu.h +0 -1
@@ -719,7 +719,6 @@ void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word);/* automatically detect the instruction length */ #define ILEN_AUTO 0xff -void program_interrupt (CPUS390XState *env,uint32_t code,int ilen);#define RA_IGNORED 0void s390_program_interrupt (CPUS390XState *env,uint32_t code,int ilen,uintptr_t ra);
target/s390x/interrupt.c +5 -17
@@ -27,17 +27,18 @@ void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen) }static void tcg_s390_program_interrupt (CPUS390XState *env,uint32_t code, -int ilen) +int ilen,uintptr_t ra) {#ifdef CONFIG_TCG trigger_pgm_exception (env, code, ilen); -cpu_loop_exit (CPU (s390_env_get_cpu (env))); +cpu_loop_exit_restore (CPU (s390_env_get_cpu (env)), ra);#else g_assert_not_reached ();#endif } -void program_interrupt (CPUS390XState *env,uint32_t code,int ilen) +void s390_program_interrupt (CPUS390XState *env,uint32_t code,int ilen, +uintptr_t ra) {S390CPU *cpu =s390_env_get_cpu (env);
@@ -47,25 +48,12 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)if (kvm_enabled ()) {kvm_s390_program_interrupt (cpu, code); }else if (tcg_enabled ()) { -tcg_s390_program_interrupt (env, code, ilen); +tcg_s390_program_interrupt (env, code, ilen, ra); }else {g_assert_not_reached (); } } -void s390_program_interrupt (CPUS390XState *env,uint32_t code,int ilen, -uintptr_t ra) -{ -#ifdef CONFIG_TCG -S390CPU *cpu =s390_env_get_cpu (env); - -if (tcg_enabled ()) { -cpu_restore_state (CPU (cpu), ra); - } -#endif -program_interrupt (env, code, ilen); -} -#if !defined(CONFIG_USER_ONLY )static void cpu_inject_service (S390CPU *cpu,uint32_t param) {
Signature · 1 line
2.14.3
PATCH v3 16/16 s390x/tcg: drop potential_page_fault()
In reply to David HildenbrandOnly one user left, get rid of it so we don't get any new users.
--- target/s390x/translate.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
target/s390x/translate.c +2 -7
@@ -240,12 +240,6 @@ static void update_cc_op(DisasContext *s) } } -static void potential_page_fault (DisasContext *s) -{ -update_psw_addr (s); -update_cc_op (s); -} -static inline uint64_t ld_code2 (CPUS390XState *env,uint64_t pc) {return (uint64_t )cpu_lduw_code (env, pc);
@@ -2939,7 +2933,8 @@ static ExitStatus op_lpd(DisasContext *s, DisasOps *o)/* In a parallel context, stop the world and single step. */ if (tb_cflags (s->tb) &CF_PARALLEL ) { -potential_page_fault (s); +update_psw_addr (s); +update_cc_op (s);gen_exception (EXCP_ATOMIC );return EXIT_NORETURN ; }
Signature · 1 line
2.14.3
Quoted 11 lines · On Thu, 30 Nov 2017 17:27:28 +0100 David Hildenbrand <[email protected]> wrote:
I have quite some patches on my queue for 2.12. (booting Fedora 26/27 guests, floating interrupts, machine checks, missing instructions ...)
So let's start slowly This series gets rid of
program_interrupt()andpotential_page_fault(). We now always properly restore the cpu state when injecting/delivering a program interrupt. So there is no need to update the state viapotential_page_fault()anymore.In addition, handling for program interrupts comming via
s390_cpu_virt_mem_rw()was missing something for the TCG case. Also fixed.
Quoted 6 lines
v2 -> v3:
- "s390x/tcg: don't exit the cpu loop ins390_cpu_virt_mem_rw()" -- don't break old KVM
- Unfortunately not able to come up with a better solution for "s390x: handle exceptions durings390_cpu_virt_mem_rw()correctly (TCG)" so I assume we'll go with this for now.
Yes, I think we should just use that for now. None of the ideas that came up were better.
Quoted 52 lines
v1 -> v2:
- renamedprogram_interrupt_ra()tos390_program_interrupt()
- introduce and useRA_IGNOREDfor KVM.
- switch tocpu_exit_loop_restore()and don't check if ra is set
- "s390x: handle exceptions durings390_cpu_virt_mem_rw()correctly (TCG)" -> split out "s390x/tcg: don't exit the cpu loop ins390_cpu_virt_mem_rw()"
- "s390x/tcg: useprogram_interrupt_ra()in SCLP Service Call" -> movedqemu_mutex_lock_iothread(); further up
- "s390x/tcg: dropprogram_interrupt()"
-> move restore totcg_s390_program_interrupt()viacpu_loop_exit_restore()
- smaller requested cleanupsDavid Hildenbrand (16):
s390x/tcg: introduce and uses390_program_interrupt()s390x/tcg: get rid ofruntime_exception()
s390x/tcg: rip out dead tpi code
s390x/ioinst: pass the retaddr to all IO instructions s390x/pci: pass the retaddr to all PCI instructions s390x/diag: pass the retaddr intohandle_diag_308()
s390x: handle exceptions durings390_cpu_virt_mem_rw()correctly (TCG) s390x/tcg: don't exit the cpu loop ins390_cpu_virt_mem_rw()s390x/tcg: io instructions don't needpotential_page_fault()s390x/tcg: uses390_program_interrupt()in SCLP Service Call s390x/tcg: uses390_program_interrupt()in DIAG
s390x/tcg: uses390_program_interrupt()inper_check_exception()s390x/tcg: uses390_program_interrupt()in SACF
s390x/tcg: uses390_program_interrupt()in STSI
s390x/tcg: dropprogram_interrupt()
s390x/tcg: droppotential_page_fault()hw/s390x/css.c | 6 --- hw/s390x/s390-pci-inst.c | 90 +++++++++++++++++++--------------- hw/s390x/s390-pci-inst.h | 16 +++--- include/hw/s390x/css.h | 1 - target/s390x/cc_helper.c | 2 +- target/s390x/cpu.h | 5 +- target/s390x/crypto_helper.c | 7 +-- target/s390x/diag.c | 14 +++--- target/s390x/excp_helper.c | 5 +- target/s390x/fpu_helper.c | 2 +- target/s390x/int_helper.c | 14 +++--- target/s390x/internal.h | 35 +++++++------- target/s390x/interrupt.c | 9 ++-- target/s390x/ioinst.c | 113 +++++++++++++++++++------------------------ target/s390x/kvm.c | 43 ++++++++-------- target/s390x/mem_helper.c | 35 +++++--------- target/s390x/misc_helper.c | 52 +++++++------------- target/s390x/mmu_helper.c | 23 +++++++-- target/s390x/translate.c | 27 +---------- 19 files changed, 228 insertions(+), 271 deletions(-)
Quoted 10 lines · On Thu, 30 Nov 2017 17:27:28 +0100 David Hildenbrand <[email protected]> wrote:
I have quite some patches on my queue for 2.12. (booting Fedora 26/27 guests, floating interrupts, machine checks, missing instructions ...)
So let's start slowly This series gets rid of
program_interrupt()andpotential_page_fault(). We now always properly restore the cpu state when injecting/delivering a program interrupt. So there is no need to update the state viapotential_page_fault()anymore.In addition, handling for program interrupts comming via
s390_cpu_virt_mem_rw()was missing something for the TCG case. Also fixed.
Thanks, queued to s390-next.