From: David Hildenbrand <david@redhat.com>
To: qemu-s390x@nongnu.org, qemu-devel@nongnu.org
Cc: Christian Borntraeger <borntraeger@de.ibm.com>,
Cornelia Huck <cohuck@redhat.com>,
Richard Henderson <rth@twiddle.net>,
Alexander Graf <agraf@suse.de>, Thomas Huth <thuth@redhat.com>,
David Hildenbrand <david@redhat.com>
Subject: [Qemu-devel] [PATCH v3 for-2.12 07/16] s390x: handle exceptions during s390_cpu_virt_mem_rw() correctly (TCG)
Date: Thu, 30 Nov 2017 17:27:35 +0100 [thread overview]
Message-ID: <20171130162744.25442-8-david@redhat.com> (raw)
In-Reply-To: <20171130162744.25442-1-david@redhat.com>
s390_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.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
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(-)
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 8123705dfd..6f41083244 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -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;
}
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 96abb2976b..ae61d18c0a 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -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 */
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index 25e0ad6f77..83c164a168 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -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);
}
}
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c
index 31e3f3f415..dbe2f511f8 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -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
--
2.14.3
next prev parent reply other threads:[~2017-11-30 16:28 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-30 16:27 [Qemu-devel] [PATCH v3 for-2.12 00/16] s390x/tcg: cleanup and fix program interrupts David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 01/16] s390x/tcg: introduce and use s390_program_interrupt() David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 02/16] s390x/tcg: get rid of runtime_exception() David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 03/16] s390x/tcg: rip out dead tpi code David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 04/16] s390x/ioinst: pass the retaddr to all IO instructions David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 05/16] s390x/pci: pass the retaddr to all PCI instructions David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 06/16] s390x/diag: pass the retaddr into handle_diag_308() David Hildenbrand
2017-11-30 16:27 ` David Hildenbrand [this message]
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 08/16] s390x/tcg: don't exit the cpu loop in s390_cpu_virt_mem_rw() David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 09/16] s390x/tcg: io instructions don't need potential_page_fault() David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 10/16] s390x/tcg: use s390_program_interrupt() in SCLP Service Call David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 11/16] s390x/tcg: use s390_program_interrupt() in DIAG David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 12/16] s390x/tcg: use s390_program_interrupt() in per_check_exception() David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 13/16] s390x/tcg: use s390_program_interrupt() in SACF David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 14/16] s390x/tcg: use s390_program_interrupt() in STSI David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 15/16] s390x/tcg: drop program_interrupt() David Hildenbrand
2017-11-30 16:27 ` [Qemu-devel] [PATCH v3 for-2.12 16/16] s390x/tcg: drop potential_page_fault() David Hildenbrand
2017-11-30 16:43 ` [Qemu-devel] [PATCH v3 for-2.12 00/16] s390x/tcg: cleanup and fix program interrupts Cornelia Huck
2017-12-01 15:38 ` Cornelia Huck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171130162744.25442-8-david@redhat.com \
--to=david@redhat.com \
--cc=agraf@suse.de \
--cc=borntraeger@de.ibm.com \
--cc=cohuck@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-s390x@nongnu.org \
--cc=rth@twiddle.net \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.