aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2020-02-05 16:47:23 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2020-02-05 16:47:23 +0100
commit5779d60cccfbd325a68837795c6884c6bf6d7e67 (patch)
treefdf16084ccfdb6a9a59edd358c6b4e1d1818f742
parent24dff0b0bf59dbd6700960167596eaebd0ac5c7d (diff)
parent00e4483399bd57c9b49f8e79c9aacf0024193536 (diff)
downloadkvm-unit-tests-5779d60cccfbd325a68837795c6884c6bf6d7e67.tar.gz
Merge tag 's390x-2020-02-04' of https://gitlab.com/huth/kvm-unit-tests into HEAD
* s390x smp patches from Janosch * Updates for the gitlab and Travis CI
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.travis.yml3
-rw-r--r--lib/s390x/interrupt.c20
-rw-r--r--lib/s390x/io.c2
-rw-r--r--lib/s390x/smp.c59
-rw-r--r--s390x/cstart64.S2
-rw-r--r--s390x/smp.c80
7 files changed, 102 insertions, 66 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cf3264d..3093239 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -64,7 +64,7 @@ build-x86_64:
- ./configure --arch=x86_64
- make -j2
- ACCEL=tcg ./run_tests.sh
- ioapic-split ioapic smptest smptest3 vmexit_cpuid vmexit_mov_from_cr8
+ smptest smptest3 vmexit_cpuid vmexit_mov_from_cr8
vmexit_mov_to_cr8 vmexit_inl_pmtimer vmexit_ipi vmexit_ipi_halt
vmexit_ple_round_robin vmexit_tscdeadline vmexit_tscdeadline_immed
eventinj msr port80 setjmp syscall tsc rmap_chain umip intel_iommu
diff --git a/.travis.yml b/.travis.yml
index 091d071..f0cfc82 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -119,5 +119,4 @@ before_script:
script:
- make -j3
- ACCEL="${ACCEL:-tcg}" ./run_tests.sh -v $TESTS | tee results.txt
- - if grep -q FAIL results.txt ; then exit 1 ; fi
- - if ! grep -q PASS results.txt ; then exit 1 ; fi
+ - grep -q PASS results.txt && ! grep -q FAIL results.txt
diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
index ccb376a..3a40cac 100644
--- a/lib/s390x/interrupt.c
+++ b/lib/s390x/interrupt.c
@@ -109,8 +109,8 @@ void handle_pgm_int(void)
if (!pgm_int_expected) {
/* Force sclp_busy to false, otherwise we will loop forever */
sclp_handle_ext();
- report_abort("Unexpected program interrupt: %d at %#lx, ilen %d\n",
- lc->pgm_int_code, lc->pgm_old_psw.addr,
+ report_abort("Unexpected program interrupt: %d on cpu %d at %#lx, ilen %d\n",
+ lc->pgm_int_code, stap(), lc->pgm_old_psw.addr,
lc->pgm_int_id);
}
@@ -122,8 +122,8 @@ void handle_ext_int(void)
{
if (!ext_int_expected &&
lc->ext_int_code != EXT_IRQ_SERVICE_SIG) {
- report_abort("Unexpected external call interrupt (code %#x): at %#lx",
- lc->ext_int_code, lc->ext_old_psw.addr);
+ report_abort("Unexpected external call interrupt (code %#x): on cpu %d at %#lx",
+ lc->ext_int_code, stap(), lc->ext_old_psw.addr);
return;
}
@@ -140,18 +140,18 @@ void handle_ext_int(void)
void handle_mcck_int(void)
{
- report_abort("Unexpected machine check interrupt: at %#lx",
- lc->mcck_old_psw.addr);
+ report_abort("Unexpected machine check interrupt: on cpu %d at %#lx",
+ stap(), lc->mcck_old_psw.addr);
}
void handle_io_int(void)
{
- report_abort("Unexpected io interrupt: at %#lx",
- lc->io_old_psw.addr);
+ report_abort("Unexpected io interrupt: on cpu %d at %#lx",
+ stap(), lc->io_old_psw.addr);
}
void handle_svc_int(void)
{
- report_abort("Unexpected supervisor call interrupt: at %#lx",
- lc->svc_old_psw.addr);
+ report_abort("Unexpected supervisor call interrupt: on cpu %d at %#lx",
+ stap(), lc->svc_old_psw.addr);
}
diff --git a/lib/s390x/io.c b/lib/s390x/io.c
index 32f09b5..e091c37 100644
--- a/lib/s390x/io.c
+++ b/lib/s390x/io.c
@@ -46,6 +46,6 @@ void exit(int code)
smp_teardown();
printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1);
while (1) {
- sigp(0, SIGP_STOP, 0, NULL);
+ sigp(stap(), SIGP_STOP, 0, NULL);
}
}
diff --git a/lib/s390x/smp.c b/lib/s390x/smp.c
index f57f420..3f86243 100644
--- a/lib/s390x/smp.c
+++ b/lib/s390x/smp.c
@@ -104,35 +104,52 @@ int smp_cpu_stop_store_status(uint16_t addr)
return rc;
}
+static int smp_cpu_restart_nolock(uint16_t addr, struct psw *psw)
+{
+ int rc;
+ struct cpu *cpu = smp_cpu_from_addr(addr);
+
+ if (!cpu)
+ return -1;
+ if (psw) {
+ cpu->lowcore->restart_new_psw.mask = psw->mask;
+ cpu->lowcore->restart_new_psw.addr = psw->addr;
+ }
+ /*
+ * Stop the cpu, so we don't have a race between a running cpu
+ * and the restart in the test that checks if the cpu is
+ * running after the restart.
+ */
+ smp_cpu_stop_nolock(addr, false);
+ rc = sigp(addr, SIGP_RESTART, 0, NULL);
+ if (rc)
+ return rc;
+ /*
+ * The order has been accepted, but the actual restart may not
+ * have been performed yet, so wait until the cpu is running.
+ */
+ while (!smp_cpu_running(addr))
+ mb();
+ cpu->active = true;
+ return 0;
+}
+
int smp_cpu_restart(uint16_t addr)
{
- int rc = -1;
- struct cpu *cpu;
+ int rc;
spin_lock(&lock);
- cpu = smp_cpu_from_addr(addr);
- if (cpu) {
- rc = sigp(addr, SIGP_RESTART, 0, NULL);
- cpu->active = true;
- }
+ rc = smp_cpu_restart_nolock(addr, NULL);
spin_unlock(&lock);
return rc;
}
int smp_cpu_start(uint16_t addr, struct psw psw)
{
- int rc = -1;
- struct cpu *cpu;
- struct lowcore *lc;
+ int rc;
spin_lock(&lock);
- cpu = smp_cpu_from_addr(addr);
- if (cpu) {
- lc = cpu->lowcore;
- lc->restart_new_psw.mask = psw.mask;
- lc->restart_new_psw.addr = psw.addr;
- rc = sigp(addr, SIGP_RESTART, 0, NULL);
- }
+ rc = smp_cpu_restart_nolock(addr, &psw);
spin_unlock(&lock);
return rc;
}
@@ -192,10 +209,10 @@ int smp_cpu_setup(uint16_t addr, struct psw psw)
lc->sw_int_crs[0] = 0x0000000000040000UL;
/* Start processing */
- rc = sigp_retry(cpu->addr, SIGP_RESTART, 0, NULL);
- if (!rc)
- cpu->active = true;
-
+ smp_cpu_restart_nolock(addr, NULL);
+ /* Wait until the cpu has finished setup and started the provided psw */
+ while (lc->restart_new_psw.addr != psw.addr)
+ mb();
out:
spin_unlock(&lock);
return rc;
diff --git a/s390x/cstart64.S b/s390x/cstart64.S
index 86dd4c4..9af6bb3 100644
--- a/s390x/cstart64.S
+++ b/s390x/cstart64.S
@@ -159,6 +159,8 @@ smp_cpu_setup_state:
xgr %r1, %r1
lmg %r0, %r15, GEN_LC_SW_INT_GRS
lctlg %c0, %c0, GEN_LC_SW_INT_CRS
+ /* We should only go once through cpu setup and not for every restart */
+ stg %r14, GEN_LC_RESTART_NEW_PSW + 8
br %r14
pgm_int:
diff --git a/s390x/smp.c b/s390x/smp.c
index ab7e46c..fa40753 100644
--- a/s390x/smp.c
+++ b/s390x/smp.c
@@ -22,6 +22,19 @@
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 cpu_loop(void)
{
for (;;) {}
@@ -29,21 +42,19 @@ static void cpu_loop(void)
static void test_func(void)
{
- testflag = 1;
- mb();
+ set_flag(1);
cpu_loop();
}
static void test_start(void)
{
struct psw psw;
- psw.mask = extract_psw_mask();
+ psw.mask = extract_psw_mask();
psw.addr = (unsigned long)test_func;
- smp_cpu_setup(1, psw);
- while (!testflag) {
- mb();
- }
+ set_flag(0);
+ smp_cpu_start(1, psw);
+ wait_for_flag();
report(1, "start");
}
@@ -98,6 +109,7 @@ static void test_store_status(void)
report(1, "status written");
free_pages(status, PAGE_SIZE * 2);
report_prefix_pop();
+ smp_cpu_stop(1);
report_prefix_pop();
}
@@ -112,27 +124,26 @@ static void ecall(void)
mask = extract_psw_mask();
mask |= PSW_MASK_EXT;
load_psw_mask(mask);
- testflag = 1;
+ set_flag(1);
while (lc->ext_int_code != 0x1202) { mb(); }
- report(1, "ecall");
- testflag= 1;
+ report(1, "received");
+ set_flag(1);
}
static void test_ecall(void)
{
struct psw psw;
- psw.mask = extract_psw_mask();
+ psw.mask = extract_psw_mask();
psw.addr = (unsigned long)ecall;
report_prefix_push("ecall");
- testflag= 0;
- smp_cpu_destroy(1);
+ set_flag(0);
- smp_cpu_setup(1, psw);
- while (!testflag) { mb(); }
- testflag= 0;
+ smp_cpu_start(1, psw);
+ wait_for_flag();
+ set_flag(0);
sigp(1, SIGP_EXTERNAL_CALL, 0, NULL);
- while(!testflag) {mb();}
+ wait_for_flag();
smp_cpu_stop(1);
report_prefix_pop();
}
@@ -147,27 +158,26 @@ static void emcall(void)
mask = extract_psw_mask();
mask |= PSW_MASK_EXT;
load_psw_mask(mask);
- testflag= 1;
+ set_flag(1);
while (lc->ext_int_code != 0x1201) { mb(); }
- report(1, "ecall");
- testflag = 1;
+ report(1, "received");
+ set_flag(1);
}
static void test_emcall(void)
{
struct psw psw;
- psw.mask = extract_psw_mask();
+ psw.mask = extract_psw_mask();
psw.addr = (unsigned long)emcall;
report_prefix_push("emcall");
- testflag= 0;
- smp_cpu_destroy(1);
+ set_flag(0);
- smp_cpu_setup(1, psw);
- while (!testflag) { mb(); }
- testflag= 0;
+ smp_cpu_start(1, psw);
+ wait_for_flag();
+ set_flag(0);
sigp(1, SIGP_EMERGENCY_SIGNAL, 0, NULL);
- while(!testflag) { mb(); }
+ wait_for_flag();
smp_cpu_stop(1);
report_prefix_pop();
}
@@ -177,11 +187,11 @@ static void test_reset_initial(void)
struct cpu_status *status = alloc_pages(0);
struct psw psw;
- psw.mask = extract_psw_mask();
+ psw.mask = extract_psw_mask();
psw.addr = (unsigned long)test_func;
report_prefix_push("reset initial");
- smp_cpu_setup(1, psw);
+ smp_cpu_start(1, psw);
sigp_retry(1, SIGP_INITIAL_CPU_RESET, 0, NULL);
sigp(1, SIGP_STORE_STATUS_AT_ADDRESS, (uintptr_t)status, NULL);
@@ -208,11 +218,11 @@ static void test_reset(void)
{
struct psw psw;
- psw.mask = extract_psw_mask();
+ psw.mask = extract_psw_mask();
psw.addr = (unsigned long)test_func;
report_prefix_push("cpu reset");
- smp_cpu_setup(1, psw);
+ smp_cpu_start(1, psw);
sigp_retry(1, SIGP_CPU_RESET, 0, NULL);
report(smp_cpu_stopped(1), "cpu stopped");
@@ -221,6 +231,7 @@ static void test_reset(void)
int main(void)
{
+ struct psw psw;
report_prefix_push("smp");
if (smp_query_num_cpus() == 1) {
@@ -228,6 +239,12 @@ int main(void)
goto done;
}
+ /* Setting up the cpu to give it a stack and lowcore */
+ psw.mask = extract_psw_mask();
+ psw.addr = (unsigned long)cpu_loop;
+ smp_cpu_setup(1, psw);
+ smp_cpu_stop(1);
+
test_start();
test_stop();
test_stop_store_status();
@@ -236,6 +253,7 @@ int main(void)
test_emcall();
test_reset();
test_reset_initial();
+ smp_cpu_destroy(1);
done:
report_prefix_pop();