From: Claudio Imbrenda <imbrenda@linux.ibm.com>
To: David Hildenbrand <david@redhat.com>
Cc: kvm@vger.kernel.org, Thomas Huth <thuth@redhat.com>,
Janosch Frank <frankja@linux.ibm.com>,
Christian Borntraeger <borntraeger@de.ibm.com>,
Sebastian Mitterle <smitterl@redhat.com>,
Halil Pasic <pasic@linux.ibm.com>,
linux-s390@vger.kernel.org
Subject: Re: [kvm-unit-tests PATCH v1 2/2] s390x: firq: floating interrupt test
Date: Thu, 2 Dec 2021 12:01:13 +0100 [thread overview]
Message-ID: <20211202120113.2dd279a8@p-imbrenda> (raw)
In-Reply-To: <20211202095843.41162-3-david@redhat.com>
On Thu, 2 Dec 2021 10:58:43 +0100
David Hildenbrand <david@redhat.com> wrote:
> We had a KVM BUG fixed by kernel commit a3e03bc1368c ("KVM: s390: index
> kvm->arch.idle_mask by vcpu_idx"), whereby a floating interrupt might get
> stuck forever because a CPU in the wait state would not get woken up.
>
> The issue can be triggered when CPUs are created in a nonlinear fashion,
> such that the CPU address ("core-id") and the KVM cpu id don't match.
>
> So let's start with a floating interrupt test that will trigger a
> floating interrupt (via SCLP) to be delivered to a CPU in the wait state.
>
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
> s390x/Makefile | 1 +
> s390x/firq.c | 141 ++++++++++++++++++++++++++++++++++++++++++++
> s390x/unittests.cfg | 10 ++++
> 3 files changed, 152 insertions(+)
> create mode 100644 s390x/firq.c
>
> diff --git a/s390x/Makefile b/s390x/Makefile
> index f95f2e6..1e567c1 100644
> --- a/s390x/Makefile
> +++ b/s390x/Makefile
> @@ -25,6 +25,7 @@ tests += $(TEST_DIR)/uv-host.elf
> tests += $(TEST_DIR)/edat.elf
> tests += $(TEST_DIR)/mvpg-sie.elf
> tests += $(TEST_DIR)/spec_ex-sie.elf
> +tests += $(TEST_DIR)/firq.elf
>
> tests_binary = $(patsubst %.elf,%.bin,$(tests))
> ifneq ($(HOST_KEY_DOCUMENT),)
> diff --git a/s390x/firq.c b/s390x/firq.c
> new file mode 100644
> index 0000000..3e60681
> --- /dev/null
> +++ b/s390x/firq.c
> @@ -0,0 +1,141 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Floating interrupt tests.
> + *
> + * Copyright 2021 Red Hat Inc
> + *
> + * Authors:
> + * David Hildenbrand <david@redhat.com>
> + */
> +#include <libcflat.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/interrupt.h>
> +#include <asm/page.h>
> +#include <asm-generic/barrier.h>
> +
> +#include <sclp.h>
> +#include <smp.h>
> +#include <alloc_page.h>
> +
> +static int testflag = 0;
> +
> +static void wait_for_flag(void)
> +{
> + while (!testflag)
> + mb();
> +}
> +
> +static void set_flag(int val)
> +{
> + mb();
> + testflag = val;
> + mb();
> +}
> +
> +static void wait_for_sclp_int(void)
> +{
> + /* Enable SCLP interrupts on this CPU only. */
> + ctl_set_bit(0, CTL0_SERVICE_SIGNAL);
> +
> + set_flag(1);
why not just WRITE_ONCE/READ_ONCE?
> +
> + /* Enable external interrupts and go to the wait state. */
> + wait_for_interrupt(PSW_MASK_EXT);
> +}
> +
> +/*
> + * Some KVM versions might mix CPUs when looking for a floating IRQ target,
> + * accidentially detecting a stopped CPU as waiting and resulting in the actually
> + * waiting CPU not getting woken up for the interrupt.
> + */
> +static void test_wait_state_delivery(void)
> +{
> + struct psw psw;
> + SCCBHeader *h;
> + int ret;
> +
> + report_prefix_push("wait state delivery");
> +
> + if (smp_query_num_cpus() < 3) {
> + report_skip("need at least 3 CPUs for this test");
> + goto out;
> + }
> +
> + if (stap()) {
> + report_skip("need to start on CPU #0");
> + goto out;
> + }
> +
> + /*
> + * We want CPU #2 to be stopped. This should be the case at this
> + * point, however, we want to sense if it even exists as well.
> + */
> + ret = smp_cpu_stop(2);
> + if (ret) {
> + report_skip("CPU #2 not found");
> + goto out;
> + }
> +
> + /*
> + * We're going to perform an SCLP service call but expect
> + * the interrupt on CPU #1 while it is in the wait state.
> + */
> + sclp_mark_busy();
this means that now no SCLP command can happen as long as the flag
stays set....
> + set_flag(0);
> +
> + /* Start CPU #1 and let it wait for the interrupt. */
> + psw.mask = extract_psw_mask();
> + psw.addr = (unsigned long)wait_for_sclp_int;
> + ret = smp_cpu_setup(1, psw);
> + if (ret) {
> + report_skip("cpu #1 not found");
...which means that this will hang, and so will all the other report*
functions. maybe you should manually unset the flag before calling the
various report* functions.
> + goto out;
> + }
> +
> + /* Wait until the CPU #1 at least enabled SCLP interrupts. */
> + wait_for_flag();
> +
> + /*
> + * We'd have to jump trough some hoops to sense e.g., via SIGP
> + * CONDITIONAL EMERGENCY SIGNAL if CPU #1 is already in the
> + * wait state.
> + *
> + * Although not completely reliable, use SIGP SENSE RUNNING STATUS
> + * until not reported as running -- after all, our SCLP processing
> + * will take some time as well and make races very rare.
> + */
> + while(smp_sense_running_status(1));
> +
> + h = alloc_page();
do you really need to dynamically allocate one page?
is there a reason for not using a simple static buffer? (which you can
have aligned and statically initialized)
> + memset(h, 0, sizeof(*h));
otherwise, if you really want to allocate the memory, get rid of the
memset; the allocator always returns zeroed memory (unless you
explicitly ask not to by using flags)
> + h->length = 4096;
> + ret = servc(SCLP_CMDW_READ_CPU_INFO, __pa(h));
> + if (ret) {
> + report_fail("SCLP_CMDW_READ_CPU_INFO failed");
> + goto out_destroy;
> + }
> +
> + /*
> + * Wait until the interrupt gets delivered on CPU #1, marking the
why do you expect the interrupt to be delivered on CPU1? could it not
be delivered on CPU0?
> + * SCLP requests as done.
> + */
> + sclp_wait_busy();
this is logically not wrong (and should stay, because it makes clear
what you are trying to do), but strictly speaking it's not needed since
the report below will hang as long as the SCLP busy flag is set.
> +
> + report(true, "firq delivered");
> +
> +out_destroy:
> + smp_cpu_destroy(1);
> + free_page(h);
> +out:
> + report_prefix_pop();
> +}
> +
> +int main(void)
> +{
> + report_prefix_push("firq");
> +
> + test_wait_state_delivery();
> +
> + report_prefix_pop();
> + return report_summary();
> +}
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index 3b454b7..054560c 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -112,3 +112,13 @@ file = mvpg-sie.elf
>
> [spec_ex-sie]
> file = spec_ex-sie.elf
> +
> +[firq-linear-cpu-ids]
> +file = firq.elf
> +timeout = 20
> +extra_params = -smp 1,maxcpus=3 -cpu qemu -device qemu-s390x-cpu,core-id=1 -device qemu-s390x-cpu,core-id=2
> +
> +[firq-nonlinear-cpu-ids]
> +file = firq.elf
> +timeout = 20
> +extra_params = -smp 1,maxcpus=3 -cpu qemu -device qemu-s390x-cpu,core-id=2 -device qemu-s390x-cpu,core-id=1
next prev parent reply other threads:[~2021-12-02 11:01 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-02 9:58 [kvm-unit-tests PATCH v1 0/2] s390x: firq: floating interrupt test David Hildenbrand
2021-12-02 9:58 ` [kvm-unit-tests PATCH v1 1/2] s390x: make smp_cpu_setup() return 0 on success David Hildenbrand
2021-12-02 10:30 ` Thomas Huth
2021-12-02 10:33 ` Claudio Imbrenda
2021-12-02 11:28 ` Janosch Frank
2021-12-02 9:58 ` [kvm-unit-tests PATCH v1 2/2] s390x: firq: floating interrupt test David Hildenbrand
2021-12-02 11:01 ` Claudio Imbrenda [this message]
2021-12-02 11:13 ` David Hildenbrand
2021-12-02 11:26 ` David Hildenbrand
2021-12-02 12:07 ` Claudio Imbrenda
2021-12-02 12:24 ` David Hildenbrand
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=20211202120113.2dd279a8@p-imbrenda \
--to=imbrenda@linux.ibm.com \
--cc=borntraeger@de.ibm.com \
--cc=david@redhat.com \
--cc=frankja@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=pasic@linux.ibm.com \
--cc=smitterl@redhat.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox