All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v2 0/3] better smp interrupt checks
@ 2022-06-24 14:45 Claudio Imbrenda
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits Claudio Imbrenda
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Claudio Imbrenda @ 2022-06-24 14:45 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, frankja, scgl, nrb, thuth

Use per-CPU flags and callbacks for Program, Extern, and I/O interrupts
instead of global variables.
    
This allows for more accurate error handling; a CPU waiting for an
interrupt will not have it "stolen" by a different CPU that was not
supposed to wait for one, and now two CPUs can wait for interrupts at
the same time.

Also fix skey.c to be compatible with the new interrupt handling.

Add some utility functions to manipulate bits in the PSW mask, to
improve readability.

Claudio Imbrenda (3):
  lib: s390x: add functions to set and clear PSW bits
  s390x: skey.c: rework the interrupt handler
  lib: s390x: better smp interrupt checks

 lib/s390x/asm/arch_def.h | 75 +++++++++++++++++++++++++++++++++++-----
 lib/s390x/asm/pgtable.h  |  2 --
 lib/s390x/smp.h          |  8 +----
 lib/s390x/interrupt.c    | 57 ++++++++++++++++++++++--------
 lib/s390x/mmu.c          | 14 +-------
 lib/s390x/sclp.c         |  7 +---
 lib/s390x/smp.c          | 11 ++++++
 s390x/diag288.c          |  6 ++--
 s390x/selftest.c         |  4 +--
 s390x/skey.c             | 24 +++++--------
 s390x/skrf.c             | 12 ++-----
 s390x/smp.c              | 18 ++--------
 12 files changed, 141 insertions(+), 97 deletions(-)

-- 
2.36.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits
  2022-06-24 14:45 [kvm-unit-tests PATCH v2 0/3] better smp interrupt checks Claudio Imbrenda
@ 2022-06-24 14:45 ` Claudio Imbrenda
  2022-06-27  8:35   ` Janosch Frank
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 2/3] s390x: skey.c: rework the interrupt handler Claudio Imbrenda
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks Claudio Imbrenda
  2 siblings, 1 reply; 9+ messages in thread
From: Claudio Imbrenda @ 2022-06-24 14:45 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, frankja, scgl, nrb, thuth

Add some functions to set and/or clear bits in the PSW.
This should improve code readability.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
 lib/s390x/asm/arch_def.h | 58 +++++++++++++++++++++++++++++++++++-----
 lib/s390x/asm/pgtable.h  |  2 --
 lib/s390x/mmu.c          | 14 +---------
 lib/s390x/sclp.c         |  7 +----
 s390x/diag288.c          |  6 ++---
 s390x/selftest.c         |  4 +--
 s390x/skrf.c             | 12 +++------
 s390x/smp.c              | 18 +++----------
 8 files changed, 63 insertions(+), 58 deletions(-)

diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index 78b257b7..b0052848 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -46,9 +46,10 @@ struct psw {
 #define AS_SECN				2
 #define AS_HOME				3
 
-#define PSW_MASK_EXT			0x0100000000000000UL
-#define PSW_MASK_IO			0x0200000000000000UL
 #define PSW_MASK_DAT			0x0400000000000000UL
+#define PSW_MASK_IO			0x0200000000000000UL
+#define PSW_MASK_EXT			0x0100000000000000UL
+#define PSW_MASK_KEY			0x00F0000000000000UL
 #define PSW_MASK_WAIT			0x0002000000000000UL
 #define PSW_MASK_PSTATE			0x0001000000000000UL
 #define PSW_MASK_EA			0x0000000100000000UL
@@ -313,6 +314,53 @@ static inline void load_psw_mask(uint64_t mask)
 		: "+r" (tmp) :  "a" (&psw) : "memory", "cc" );
 }
 
+/**
+ * psw_mask_set_clear_bits - sets and clears bits from the current PSW mask
+ * @clear: bitmask of bits that will be cleared
+ * @set: bitmask of bits that will be set
+ *
+ * Bits will be cleared first, and then set, so if (@clear & @set != 0) then
+ * the bits in the intersection will be set.
+ */
+static inline void psw_mask_set_clear_bits(uint64_t clear, uint64_t set)
+{
+	load_psw_mask((extract_psw_mask() & ~clear) | set);
+}
+
+/**
+ * psw_mask_clear_bits - clears bits from the current PSW mask
+ * @clear: bitmask of bits that will be cleared
+ */
+static inline void psw_mask_clear_bits(uint64_t clear)
+{
+	load_psw_mask(extract_psw_mask() & ~clear);
+}
+
+/**
+ * psw_mask_set_bits - sets bits on the current PSW mask
+ * @set: bitmask of bits that will be set
+ */
+static inline void psw_mask_set_bits(uint64_t set)
+{
+	load_psw_mask(extract_psw_mask() | set);
+}
+
+/**
+ * enable_dat - enable the DAT bit in the current PSW
+ */
+static inline void enable_dat(void)
+{
+	psw_mask_set_bits(PSW_MASK_DAT);
+}
+
+/**
+ * disable_dat - disable the DAT bit in the current PSW
+ */
+static inline void disable_dat(void)
+{
+	psw_mask_clear_bits(PSW_MASK_DAT);
+}
+
 static inline void wait_for_interrupt(uint64_t irq_mask)
 {
 	uint64_t psw_mask = extract_psw_mask();
@@ -327,11 +375,7 @@ static inline void wait_for_interrupt(uint64_t irq_mask)
 
 static inline void enter_pstate(void)
 {
-	uint64_t mask;
-
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_PSTATE;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_PSTATE);
 }
 
 static inline void leave_pstate(void)
diff --git a/lib/s390x/asm/pgtable.h b/lib/s390x/asm/pgtable.h
index f166dcc6..7b556ad9 100644
--- a/lib/s390x/asm/pgtable.h
+++ b/lib/s390x/asm/pgtable.h
@@ -247,6 +247,4 @@ static inline void idte_pgdp(unsigned long vaddr, pgdval_t *pgdp)
 	idte((unsigned long)(pgdp - pgd_index(vaddr)) | ASCE_DT_REGION1, vaddr);
 }
 
-void configure_dat(int enable);
-
 #endif /* _ASMS390X_PGTABLE_H_ */
diff --git a/lib/s390x/mmu.c b/lib/s390x/mmu.c
index c9f8754c..b474d702 100644
--- a/lib/s390x/mmu.c
+++ b/lib/s390x/mmu.c
@@ -29,18 +29,6 @@
 
 static pgd_t *table_root;
 
-void configure_dat(int enable)
-{
-	uint64_t mask;
-
-	if (enable)
-		mask = extract_psw_mask() | PSW_MASK_DAT;
-	else
-		mask = extract_psw_mask() & ~PSW_MASK_DAT;
-
-	load_psw_mask(mask);
-}
-
 static void mmu_enable(pgd_t *pgtable)
 {
 	const uint64_t asce = __pa(pgtable) | ASCE_DT_REGION1 |
@@ -51,7 +39,7 @@ static void mmu_enable(pgd_t *pgtable)
 	assert(stctg(1) == asce);
 
 	/* enable dat (primary == 0 set as default) */
-	configure_dat(1);
+	enable_dat();
 
 	/* we can now also use DAT unconditionally in our PGM handler */
 	lowcore.pgm_new_psw.mask |= PSW_MASK_DAT;
diff --git a/lib/s390x/sclp.c b/lib/s390x/sclp.c
index b8204c5f..a806cdb3 100644
--- a/lib/s390x/sclp.c
+++ b/lib/s390x/sclp.c
@@ -48,13 +48,8 @@ static void mem_init(phys_addr_t mem_end)
 
 void sclp_setup_int(void)
 {
-	uint64_t mask;
-
 	ctl_set_bit(0, CTL0_SERVICE_SIGNAL);
-
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_EXT;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_EXT);
 }
 
 void sclp_handle_ext(void)
diff --git a/s390x/diag288.c b/s390x/diag288.c
index e414865b..46dc0ed8 100644
--- a/s390x/diag288.c
+++ b/s390x/diag288.c
@@ -78,16 +78,14 @@ static void test_priv(void)
 
 static void test_bite(void)
 {
-	uint64_t mask, time;
+	uint64_t time;
 
 	/* If watchdog doesn't bite, the cpu timer does */
 	asm volatile("stck %0" : "=Q" (time) : : "cc");
 	time += (uint64_t)(16000 * 1000) << 12;
 	asm volatile("sckc %0" : : "Q" (time));
 	ctl_set_bit(0, CTL0_CLOCK_COMPARATOR);
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_EXT;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_EXT);
 
 	/* Arm watchdog */
 	lowcore.restart_new_psw.mask = extract_psw_mask() & ~PSW_MASK_EXT;
diff --git a/s390x/selftest.c b/s390x/selftest.c
index 239bc5e3..13fd36bc 100644
--- a/s390x/selftest.c
+++ b/s390x/selftest.c
@@ -64,9 +64,9 @@ static void test_malloc(void)
 	report(tmp != tmp2, "allocated memory addresses differ");
 
 	expect_pgm_int();
-	configure_dat(0);
+	disable_dat();
 	*tmp = 987654321;
-	configure_dat(1);
+	enable_dat();
 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
 
 	free(tmp);
diff --git a/s390x/skrf.c b/s390x/skrf.c
index 1a811894..26f70b4e 100644
--- a/s390x/skrf.c
+++ b/s390x/skrf.c
@@ -63,11 +63,9 @@ static void test_pfmf(void)
 
 static void test_psw_key(void)
 {
-	uint64_t psw_mask = extract_psw_mask() | 0xF0000000000000UL;
-
 	report_prefix_push("psw key");
 	expect_pgm_int();
-	load_psw_mask(psw_mask);
+	psw_mask_set_bits(PSW_MASK_KEY);
 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
 	report_prefix_pop();
 }
@@ -140,17 +138,13 @@ static void ecall_cleanup(void)
 /* Set a key into the external new psw mask and open external call masks */
 static void ecall_setup(void)
 {
-	uint64_t mask;
-
 	register_pgm_cleanup_func(ecall_cleanup);
 	expect_pgm_int();
 	/* Put a skey into the ext new psw */
-	lowcore.ext_new_psw.mask = 0x00F0000000000000UL | PSW_MASK_64;
+	lowcore.ext_new_psw.mask = PSW_MASK_KEY | PSW_MASK_64;
 	/* Open up ext masks */
 	ctl_set_bit(0, CTL0_EXTERNAL_CALL);
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_EXT;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_EXT);
 	/* Tell cpu 0 that we're ready */
 	set_flag(1);
 }
diff --git a/s390x/smp.c b/s390x/smp.c
index 6d474d0d..0df4751f 100644
--- a/s390x/smp.c
+++ b/s390x/smp.c
@@ -288,13 +288,9 @@ static void test_set_prefix(void)
 
 static void ecall(void)
 {
-	unsigned long mask;
-
 	expect_ext_int();
 	ctl_set_bit(0, CTL0_EXTERNAL_CALL);
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_EXT;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_EXT);
 	set_flag(1);
 	while (lowcore.ext_int_code != 0x1202) { mb(); }
 	report_pass("received");
@@ -321,13 +317,9 @@ static void test_ecall(void)
 
 static void emcall(void)
 {
-	unsigned long mask;
-
 	expect_ext_int();
 	ctl_set_bit(0, CTL0_EMERGENCY_SIGNAL);
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_EXT;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_EXT);
 	set_flag(1);
 	while (lowcore.ext_int_code != 0x1201) { mb(); }
 	report_pass("received");
@@ -466,14 +458,10 @@ static void test_reset_initial(void)
 
 static void test_local_ints(void)
 {
-	unsigned long mask;
-
 	/* Open masks for ecall and emcall */
 	ctl_set_bit(0, CTL0_EXTERNAL_CALL);
 	ctl_set_bit(0, CTL0_EMERGENCY_SIGNAL);
-	mask = extract_psw_mask();
-	mask |= PSW_MASK_EXT;
-	load_psw_mask(mask);
+	psw_mask_set_bits(PSW_MASK_EXT);
 	set_flag(1);
 }
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [kvm-unit-tests PATCH v2 2/3] s390x: skey.c: rework the interrupt handler
  2022-06-24 14:45 [kvm-unit-tests PATCH v2 0/3] better smp interrupt checks Claudio Imbrenda
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits Claudio Imbrenda
@ 2022-06-24 14:45 ` Claudio Imbrenda
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks Claudio Imbrenda
  2 siblings, 0 replies; 9+ messages in thread
From: Claudio Imbrenda @ 2022-06-24 14:45 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, frankja, scgl, nrb, thuth

The skey test currently uses a cleanup function to work around the
issues that arise when the lowcore is not mapped, since the interrupt
handler needs to access it.

Instead of a cleanup function, simply disable DAT for the interrupt
handler for the tests that remap page 0. This is needed in preparation
of and upcoming patch that will cause the interrupt handler to read
from lowcore before calling the cleanup function.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
 s390x/skey.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/s390x/skey.c b/s390x/skey.c
index 445476a0..24123763 100644
--- a/s390x/skey.c
+++ b/s390x/skey.c
@@ -15,7 +15,6 @@
 #include <asm/facility.h>
 #include <asm/mem.h>
 
-
 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
 
 static void test_set_mb(void)
@@ -250,19 +249,6 @@ static void set_prefix_key_1(uint32_t *prefix_ptr)
 	);
 }
 
-/*
- * We remapped page 0, making the lowcore inaccessible, which breaks the normal
- * handler and breaks skipping the faulting instruction.
- * Just disable dynamic address translation to make things work.
- */
-static void dat_fixup_pgm_int(void)
-{
-	uint64_t psw_mask = extract_psw_mask();
-
-	psw_mask &= ~PSW_MASK_DAT;
-	load_psw_mask(psw_mask);
-}
-
 #define PREFIX_AREA_SIZE (PAGE_SIZE * 2)
 static char lowcore_tmp[PREFIX_AREA_SIZE] __attribute__((aligned(PREFIX_AREA_SIZE)));
 
@@ -318,7 +304,13 @@ static void test_set_prefix(void)
 	report(get_prefix() == old_prefix, "did not set prefix");
 	report_prefix_pop();
 
-	register_pgm_cleanup_func(dat_fixup_pgm_int);
+	/*
+	 * Page 0 will be remapped, making the lowcore inaccessible, which
+	 * breaks the normal handler and breaks skipping the faulting
+	 * instruction. Disable dynamic address translation for the
+	 * interrupt handler to make things work.
+	 */
+	lowcore.pgm_new_psw.mask &= ~PSW_MASK_DAT;
 
 	report_prefix_push("remapped page, fetch protection");
 	set_prefix(old_prefix);
@@ -356,7 +348,7 @@ static void test_set_prefix(void)
 	report_prefix_pop();
 
 	ctl_clear_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE);
-	register_pgm_cleanup_func(NULL);
+	lowcore.pgm_new_psw.mask |= PSW_MASK_DAT;
 	report_prefix_pop();
 	set_storage_key(pagebuf, 0x00, 0);
 	report_prefix_pop();
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks
  2022-06-24 14:45 [kvm-unit-tests PATCH v2 0/3] better smp interrupt checks Claudio Imbrenda
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits Claudio Imbrenda
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 2/3] s390x: skey.c: rework the interrupt handler Claudio Imbrenda
@ 2022-06-24 14:45 ` Claudio Imbrenda
  2022-06-27  9:28   ` Janosch Frank
  2 siblings, 1 reply; 9+ messages in thread
From: Claudio Imbrenda @ 2022-06-24 14:45 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, frankja, scgl, nrb, thuth

Use per-CPU flags and callbacks for Program and Extern interrupts,
instead of global variables.

This allows for more accurate error handling; a CPU waiting for an
interrupt will not have it "stolen" by a different CPU that was not
supposed to wait for one, and now two CPUs can wait for interrupts at
the same time.

This will significantly improve error reporting and debugging when
things go wrong.

Both program interrupts and extern interrupts are now CPU-bound, even
though some extern interrupts are floating (notably, the SCLP
interrupt). In those cases, the testcases should mask interrupts and/or
expect them appropriately according to need.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
 lib/s390x/asm/arch_def.h | 17 +++++++++++-
 lib/s390x/smp.h          |  8 +-----
 lib/s390x/interrupt.c    | 57 +++++++++++++++++++++++++++++-----------
 lib/s390x/smp.c          | 11 ++++++++
 4 files changed, 70 insertions(+), 23 deletions(-)

diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index b0052848..9fefdbff 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -41,6 +41,18 @@ struct psw {
 	uint64_t	addr;
 };
 
+struct cpu {
+	struct lowcore *lowcore;
+	uint64_t *stack;
+	void (*pgm_cleanup_func)(void);
+	void (*ext_cleanup_func)(void);
+	uint16_t addr;
+	uint16_t idx;
+	bool active;
+	bool pgm_int_expected;
+	bool ext_int_expected;
+};
+
 #define AS_PRIM				0
 #define AS_ACCR				1
 #define AS_SECN				2
@@ -125,7 +137,8 @@ struct lowcore {
 	uint8_t		pad_0x0280[0x0308 - 0x0280];	/* 0x0280 */
 	uint64_t	sw_int_crs[16];			/* 0x0308 */
 	struct psw	sw_int_psw;			/* 0x0388 */
-	uint8_t		pad_0x0310[0x11b0 - 0x0398];	/* 0x0398 */
+	struct cpu *	this_cpu;			/* 0x0398 */
+	uint8_t		pad_0x03a0[0x11b0 - 0x03a0];	/* 0x03a0 */
 	uint64_t	mcck_ext_sa_addr;		/* 0x11b0 */
 	uint8_t		pad_0x11b8[0x1200 - 0x11b8];	/* 0x11b8 */
 	uint64_t	fprs_sa[16];			/* 0x1200 */
@@ -148,6 +161,8 @@ _Static_assert(sizeof(struct lowcore) == 0x1900, "Lowcore size");
 
 extern struct lowcore lowcore;
 
+#define THIS_CPU (lowcore.this_cpu)
+
 #define PGM_INT_CODE_OPERATION			0x01
 #define PGM_INT_CODE_PRIVILEGED_OPERATION	0x02
 #define PGM_INT_CODE_EXECUTE			0x03
diff --git a/lib/s390x/smp.h b/lib/s390x/smp.h
index df184cb8..f4ae973d 100644
--- a/lib/s390x/smp.h
+++ b/lib/s390x/smp.h
@@ -12,13 +12,6 @@
 
 #include <asm/arch_def.h>
 
-struct cpu {
-	struct lowcore *lowcore;
-	uint64_t *stack;
-	uint16_t addr;
-	bool active;
-};
-
 struct cpu_status {
     uint64_t    fprs[16];                       /* 0x0000 */
     uint64_t    grs[16];                        /* 0x0080 */
@@ -52,5 +45,6 @@ int smp_cpu_setup(uint16_t idx, struct psw psw);
 void smp_teardown(void);
 void smp_setup(void);
 int smp_sigp(uint16_t idx, uint8_t order, unsigned long parm, uint32_t *status);
+struct lowcore *smp_get_lowcore(uint16_t idx);
 
 #endif
diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
index 6da20c44..45f16429 100644
--- a/lib/s390x/interrupt.c
+++ b/lib/s390x/interrupt.c
@@ -15,25 +15,36 @@
 #include <fault.h>
 #include <asm/page.h>
 
-static bool pgm_int_expected;
-static bool ext_int_expected;
-static void (*pgm_cleanup_func)(void);
-
+/**
+ * expect_pgm_int - Expect a program interrupt on the current CPU.
+ */
 void expect_pgm_int(void)
 {
-	pgm_int_expected = true;
+	THIS_CPU->pgm_int_expected = true;
 	lowcore.pgm_int_code = 0;
 	lowcore.trans_exc_id = 0;
 	mb();
 }
 
+/**
+ * expect_ext_int - Expect an extern interrupt on the current CPU.
+ */
 void expect_ext_int(void)
 {
-	ext_int_expected = true;
+	THIS_CPU->ext_int_expected = true;
 	lowcore.ext_int_code = 0;
 	mb();
 }
 
+/**
+ * clear_pgm_int - Clear program interrupt information
+ *
+ * Clear program interrupt information, including the expected program
+ * interrupt flag.
+ * No program interrupts are expected after calling this function.
+ *
+ * Return: the program interrupt code before clearing
+ */
 uint16_t clear_pgm_int(void)
 {
 	uint16_t code;
@@ -42,10 +53,17 @@ uint16_t clear_pgm_int(void)
 	code = lowcore.pgm_int_code;
 	lowcore.pgm_int_code = 0;
 	lowcore.trans_exc_id = 0;
-	pgm_int_expected = false;
+	THIS_CPU->pgm_int_expected = false;
 	return code;
 }
 
+/**
+ * check_pgm_int_code - Check the program interrupt code on the current CPU.
+ * @code the expected program interrupt code on the current CPU
+ *
+ * Check and report if the program interrupt on the current CPU matches the
+ * expected one.
+ */
 void check_pgm_int_code(uint16_t code)
 {
 	mb();
@@ -54,9 +72,19 @@ void check_pgm_int_code(uint16_t code)
 	       lowcore.pgm_int_code);
 }
 
+/**
+ * register_pgm_cleanup_func - Register a cleanup function for progam
+ * interrupts for the current CPU.
+ * @f the cleanup function to be registered on the current CPU
+ *
+ * Register a cleanup function to be called at the end of the normal
+ * interrupt handling for program interrupts for this CPU.
+ *
+ * Pass NULL to unregister a previously registered cleanup function.
+ */
 void register_pgm_cleanup_func(void (*f)(void))
 {
-	pgm_cleanup_func = f;
+	THIS_CPU->pgm_cleanup_func = f;
 }
 
 static void fixup_pgm_int(struct stack_frame_int *stack)
@@ -183,24 +211,23 @@ static void print_pgm_info(struct stack_frame_int *stack)
 
 void handle_pgm_int(struct stack_frame_int *stack)
 {
-	if (!pgm_int_expected) {
+	if (!THIS_CPU->pgm_int_expected) {
 		/* Force sclp_busy to false, otherwise we will loop forever */
 		sclp_handle_ext();
 		print_pgm_info(stack);
 	}
 
-	pgm_int_expected = false;
+	THIS_CPU->pgm_int_expected = false;
 
-	if (pgm_cleanup_func)
-		(*pgm_cleanup_func)();
+	if (THIS_CPU->pgm_cleanup_func)
+		THIS_CPU->pgm_cleanup_func();
 	else
 		fixup_pgm_int(stack);
 }
 
 void handle_ext_int(struct stack_frame_int *stack)
 {
-	if (!ext_int_expected &&
-	    lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG) {
+	if (!THIS_CPU->ext_int_expected && lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG) {
 		report_abort("Unexpected external call interrupt (code %#x): on cpu %d at %#lx",
 			     lowcore.ext_int_code, stap(), lowcore.ext_old_psw.addr);
 		return;
@@ -210,7 +237,7 @@ void handle_ext_int(struct stack_frame_int *stack)
 		stack->crs[0] &= ~(1UL << 9);
 		sclp_handle_ext();
 	} else {
-		ext_int_expected = false;
+		THIS_CPU->ext_int_expected = false;
 	}
 
 	if (!(stack->crs[0] & CR0_EXTM_MASK))
diff --git a/lib/s390x/smp.c b/lib/s390x/smp.c
index a0495cd9..65ea524c 100644
--- a/lib/s390x/smp.c
+++ b/lib/s390x/smp.c
@@ -39,6 +39,15 @@ int smp_query_num_cpus(void)
 	return sclp_get_cpu_num();
 }
 
+struct lowcore *smp_get_lowcore(uint16_t idx)
+{
+	if (THIS_CPU->idx == idx)
+		return &lowcore;
+
+	check_idx(idx);
+	return cpus[idx].lowcore;
+}
+
 int smp_sigp(uint16_t idx, uint8_t order, unsigned long parm, uint32_t *status)
 {
 	check_idx(idx);
@@ -253,6 +262,7 @@ static int smp_cpu_setup_nolock(uint16_t idx, struct psw psw)
 
 	/* Copy all exception psws. */
 	memcpy(lc, cpus[0].lowcore, 512);
+	lc->this_cpu = cpus + idx;
 
 	/* Setup stack */
 	cpus[idx].stack = (uint64_t *)alloc_pages(2);
@@ -325,6 +335,7 @@ void smp_setup(void)
 	for (i = 0; i < num; i++) {
 		cpus[i].addr = entry[i].address;
 		cpus[i].active = false;
+		cpus[i].idx = i;
 		/*
 		 * Fill in the boot CPU. If the boot CPU is not at index 0,
 		 * swap it with the one at index 0. This guarantees that the
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits Claudio Imbrenda
@ 2022-06-27  8:35   ` Janosch Frank
  2022-06-27 10:47     ` Claudio Imbrenda
  0 siblings, 1 reply; 9+ messages in thread
From: Janosch Frank @ 2022-06-27  8:35 UTC (permalink / raw)
  To: Claudio Imbrenda, kvm; +Cc: linux-s390, scgl, nrb, thuth

On 6/24/22 16:45, Claudio Imbrenda wrote:
> Add some functions to set and/or clear bits in the PSW.
> This should improve code readability.
> 

Also we introduce PSW_MASK_KEY and re-order the PSW_MASK_* constants so 
they are descending in value.

> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> ---
>   lib/s390x/asm/arch_def.h | 58 +++++++++++++++++++++++++++++++++++-----
>   lib/s390x/asm/pgtable.h  |  2 --
>   lib/s390x/mmu.c          | 14 +---------
>   lib/s390x/sclp.c         |  7 +----
>   s390x/diag288.c          |  6 ++---
>   s390x/selftest.c         |  4 +--
>   s390x/skrf.c             | 12 +++------
>   s390x/smp.c              | 18 +++----------
>   8 files changed, 63 insertions(+), 58 deletions(-)
> 
> diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
> index 78b257b7..b0052848 100644
> --- a/lib/s390x/asm/arch_def.h
> +++ b/lib/s390x/asm/arch_def.h
> @@ -46,9 +46,10 @@ struct psw {
>   #define AS_SECN				2
>   #define AS_HOME				3
>   
> -#define PSW_MASK_EXT			0x0100000000000000UL
> -#define PSW_MASK_IO			0x0200000000000000UL
>   #define PSW_MASK_DAT			0x0400000000000000UL
> +#define PSW_MASK_IO			0x0200000000000000UL
> +#define PSW_MASK_EXT			0x0100000000000000UL
> +#define PSW_MASK_KEY			0x00F0000000000000UL
>   #define PSW_MASK_WAIT			0x0002000000000000UL
>   #define PSW_MASK_PSTATE			0x0001000000000000UL
>   #define PSW_MASK_EA			0x0000000100000000UL
> @@ -313,6 +314,53 @@ static inline void load_psw_mask(uint64_t mask)
>   		: "+r" (tmp) :  "a" (&psw) : "memory", "cc" );
>   }
>   
> +/**
> + * psw_mask_set_clear_bits - sets and clears bits from the current PSW mask
> + * @clear: bitmask of bits that will be cleared
> + * @set: bitmask of bits that will be set
> + *
> + * Bits will be cleared first, and then set, so if (@clear & @set != 0) then
> + * the bits in the intersection will be set.
> + */
> +static inline void psw_mask_set_clear_bits(uint64_t clear, uint64_t set)

This function isn't used at all, no?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks
  2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks Claudio Imbrenda
@ 2022-06-27  9:28   ` Janosch Frank
  2022-06-27 10:53     ` Claudio Imbrenda
  0 siblings, 1 reply; 9+ messages in thread
From: Janosch Frank @ 2022-06-27  9:28 UTC (permalink / raw)
  To: Claudio Imbrenda, kvm; +Cc: linux-s390, scgl, nrb, thuth

On 6/24/22 16:45, Claudio Imbrenda wrote:
> Use per-CPU flags and callbacks for Program and Extern interrupts,
> instead of global variables.
> 
> This allows for more accurate error handling; a CPU waiting for an
> interrupt will not have it "stolen" by a different CPU that was not
> supposed to wait for one, and now two CPUs can wait for interrupts at
> the same time.
> 
> This will significantly improve error reporting and debugging when
> things go wrong.
> 
> Both program interrupts and extern interrupts are now CPU-bound, even
> though some extern interrupts are floating (notably, the SCLP
> interrupt). In those cases, the testcases should mask interrupts and/or
> expect them appropriately according to need.
> 
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> ---
>   lib/s390x/asm/arch_def.h | 17 +++++++++++-
>   lib/s390x/smp.h          |  8 +-----
>   lib/s390x/interrupt.c    | 57 +++++++++++++++++++++++++++++-----------
>   lib/s390x/smp.c          | 11 ++++++++
>   4 files changed, 70 insertions(+), 23 deletions(-)
[...]
>   
> +struct lowcore *smp_get_lowcore(uint16_t idx)
> +{
> +	if (THIS_CPU->idx == idx)
> +		return &lowcore;
> +
> +	check_idx(idx);
> +	return cpus[idx].lowcore;
> +}

This function is unused.

> +
>   int smp_sigp(uint16_t idx, uint8_t order, unsigned long parm, uint32_t *status)
>   {
>   	check_idx(idx);
> @@ -253,6 +262,7 @@ static int smp_cpu_setup_nolock(uint16_t idx, struct psw psw)
>   
>   	/* Copy all exception psws. */
>   	memcpy(lc, cpus[0].lowcore, 512);
> +	lc->this_cpu = cpus + idx;

Why not:
lc->this_cpu = &cpus[idx];

>   
>   	/* Setup stack */
>   	cpus[idx].stack = (uint64_t *)alloc_pages(2);
> @@ -325,6 +335,7 @@ void smp_setup(void)
>   	for (i = 0; i < num; i++) {
>   		cpus[i].addr = entry[i].address;
>   		cpus[i].active = false;
> +		cpus[i].idx = i;
>   		/*
>   		 * Fill in the boot CPU. If the boot CPU is not at index 0,
>   		 * swap it with the one at index 0. This guarantees that the


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits
  2022-06-27  8:35   ` Janosch Frank
@ 2022-06-27 10:47     ` Claudio Imbrenda
  0 siblings, 0 replies; 9+ messages in thread
From: Claudio Imbrenda @ 2022-06-27 10:47 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, scgl, nrb, thuth

On Mon, 27 Jun 2022 10:35:11 +0200
Janosch Frank <frankja@linux.ibm.com> wrote:

> On 6/24/22 16:45, Claudio Imbrenda wrote:
> > Add some functions to set and/or clear bits in the PSW.
> > This should improve code readability.
> >   
> 
> Also we introduce PSW_MASK_KEY and re-order the PSW_MASK_* constants so 
> they are descending in value.

will fix the description

> 
> > Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> > ---
> >   lib/s390x/asm/arch_def.h | 58 +++++++++++++++++++++++++++++++++++-----
> >   lib/s390x/asm/pgtable.h  |  2 --
> >   lib/s390x/mmu.c          | 14 +---------
> >   lib/s390x/sclp.c         |  7 +----
> >   s390x/diag288.c          |  6 ++---
> >   s390x/selftest.c         |  4 +--
> >   s390x/skrf.c             | 12 +++------
> >   s390x/smp.c              | 18 +++----------
> >   8 files changed, 63 insertions(+), 58 deletions(-)
> > 
> > diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
> > index 78b257b7..b0052848 100644
> > --- a/lib/s390x/asm/arch_def.h
> > +++ b/lib/s390x/asm/arch_def.h
> > @@ -46,9 +46,10 @@ struct psw {
> >   #define AS_SECN				2
> >   #define AS_HOME				3
> >   
> > -#define PSW_MASK_EXT			0x0100000000000000UL
> > -#define PSW_MASK_IO			0x0200000000000000UL
> >   #define PSW_MASK_DAT			0x0400000000000000UL
> > +#define PSW_MASK_IO			0x0200000000000000UL
> > +#define PSW_MASK_EXT			0x0100000000000000UL
> > +#define PSW_MASK_KEY			0x00F0000000000000UL
> >   #define PSW_MASK_WAIT			0x0002000000000000UL
> >   #define PSW_MASK_PSTATE			0x0001000000000000UL
> >   #define PSW_MASK_EA			0x0000000100000000UL
> > @@ -313,6 +314,53 @@ static inline void load_psw_mask(uint64_t mask)
> >   		: "+r" (tmp) :  "a" (&psw) : "memory", "cc" );
> >   }
> >   
> > +/**
> > + * psw_mask_set_clear_bits - sets and clears bits from the current PSW mask
> > + * @clear: bitmask of bits that will be cleared
> > + * @set: bitmask of bits that will be set
> > + *
> > + * Bits will be cleared first, and then set, so if (@clear & @set != 0) then
> > + * the bits in the intersection will be set.
> > + */
> > +static inline void psw_mask_set_clear_bits(uint64_t clear, uint64_t set)  
> 
> This function isn't used at all, no?

not currently, but it's useful to have in the lib

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks
  2022-06-27  9:28   ` Janosch Frank
@ 2022-06-27 10:53     ` Claudio Imbrenda
  2022-06-27 11:09       ` Janosch Frank
  0 siblings, 1 reply; 9+ messages in thread
From: Claudio Imbrenda @ 2022-06-27 10:53 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, scgl, nrb, thuth

On Mon, 27 Jun 2022 11:28:18 +0200
Janosch Frank <frankja@linux.ibm.com> wrote:

> On 6/24/22 16:45, Claudio Imbrenda wrote:
> > Use per-CPU flags and callbacks for Program and Extern interrupts,
> > instead of global variables.
> > 
> > This allows for more accurate error handling; a CPU waiting for an
> > interrupt will not have it "stolen" by a different CPU that was not
> > supposed to wait for one, and now two CPUs can wait for interrupts at
> > the same time.
> > 
> > This will significantly improve error reporting and debugging when
> > things go wrong.
> > 
> > Both program interrupts and extern interrupts are now CPU-bound, even
> > though some extern interrupts are floating (notably, the SCLP
> > interrupt). In those cases, the testcases should mask interrupts and/or
> > expect them appropriately according to need.
> > 
> > Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> > ---
> >   lib/s390x/asm/arch_def.h | 17 +++++++++++-
> >   lib/s390x/smp.h          |  8 +-----
> >   lib/s390x/interrupt.c    | 57 +++++++++++++++++++++++++++++-----------
> >   lib/s390x/smp.c          | 11 ++++++++
> >   4 files changed, 70 insertions(+), 23 deletions(-)  
> [...]
> >   
> > +struct lowcore *smp_get_lowcore(uint16_t idx)
> > +{
> > +	if (THIS_CPU->idx == idx)
> > +		return &lowcore;
> > +
> > +	check_idx(idx);
> > +	return cpus[idx].lowcore;
> > +}  
> 
> This function is unused.

not currently, but it's useful to have in lib

should I split this into a separate patch?

> 
> > +
> >   int smp_sigp(uint16_t idx, uint8_t order, unsigned long parm, uint32_t *status)
> >   {
> >   	check_idx(idx);
> > @@ -253,6 +262,7 @@ static int smp_cpu_setup_nolock(uint16_t idx, struct psw psw)
> >   
> >   	/* Copy all exception psws. */
> >   	memcpy(lc, cpus[0].lowcore, 512);
> > +	lc->this_cpu = cpus + idx;  
> 
> Why not:
> lc->this_cpu = &cpus[idx];

it's equivalent, do you have a reason for changing it?

> 
> >   
> >   	/* Setup stack */
> >   	cpus[idx].stack = (uint64_t *)alloc_pages(2);
> > @@ -325,6 +335,7 @@ void smp_setup(void)
> >   	for (i = 0; i < num; i++) {
> >   		cpus[i].addr = entry[i].address;
> >   		cpus[i].active = false;
> > +		cpus[i].idx = i;
> >   		/*
> >   		 * Fill in the boot CPU. If the boot CPU is not at index 0,
> >   		 * swap it with the one at index 0. This guarantees that the  
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks
  2022-06-27 10:53     ` Claudio Imbrenda
@ 2022-06-27 11:09       ` Janosch Frank
  0 siblings, 0 replies; 9+ messages in thread
From: Janosch Frank @ 2022-06-27 11:09 UTC (permalink / raw)
  To: Claudio Imbrenda; +Cc: kvm, linux-s390, scgl, nrb, thuth

On 6/27/22 12:53, Claudio Imbrenda wrote:
> On Mon, 27 Jun 2022 11:28:18 +0200
> Janosch Frank <frankja@linux.ibm.com> wrote:
> 
>> On 6/24/22 16:45, Claudio Imbrenda wrote:
>>> Use per-CPU flags and callbacks for Program and Extern interrupts,
>>> instead of global variables.
>>>
>>> This allows for more accurate error handling; a CPU waiting for an
>>> interrupt will not have it "stolen" by a different CPU that was not
>>> supposed to wait for one, and now two CPUs can wait for interrupts at
>>> the same time.
>>>
>>> This will significantly improve error reporting and debugging when
>>> things go wrong.
>>>
>>> Both program interrupts and extern interrupts are now CPU-bound, even
>>> though some extern interrupts are floating (notably, the SCLP
>>> interrupt). In those cases, the testcases should mask interrupts and/or
>>> expect them appropriately according to need.
>>>
>>> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
>>> ---
>>>    lib/s390x/asm/arch_def.h | 17 +++++++++++-
>>>    lib/s390x/smp.h          |  8 +-----
>>>    lib/s390x/interrupt.c    | 57 +++++++++++++++++++++++++++++-----------
>>>    lib/s390x/smp.c          | 11 ++++++++
>>>    4 files changed, 70 insertions(+), 23 deletions(-)
>> [...]
>>>    
>>> +struct lowcore *smp_get_lowcore(uint16_t idx)
>>> +{
>>> +	if (THIS_CPU->idx == idx)
>>> +		return &lowcore;
>>> +
>>> +	check_idx(idx);
>>> +	return cpus[idx].lowcore;
>>> +}
>>
>> This function is unused.
> 
> not currently, but it's useful to have in lib
> 
> should I split this into a separate patch?
> 
>>
>>> +
>>>    int smp_sigp(uint16_t idx, uint8_t order, unsigned long parm, uint32_t *status)
>>>    {
>>>    	check_idx(idx);
>>> @@ -253,6 +262,7 @@ static int smp_cpu_setup_nolock(uint16_t idx, struct psw psw)
>>>    
>>>    	/* Copy all exception psws. */
>>>    	memcpy(lc, cpus[0].lowcore, 512);
>>> +	lc->this_cpu = cpus + idx;
>>
>> Why not:
>> lc->this_cpu = &cpus[idx];
> 
> it's equivalent, do you have a reason for changing it?

It's more explicit.

> 
>>
>>>    
>>>    	/* Setup stack */
>>>    	cpus[idx].stack = (uint64_t *)alloc_pages(2);
>>> @@ -325,6 +335,7 @@ void smp_setup(void)
>>>    	for (i = 0; i < num; i++) {
>>>    		cpus[i].addr = entry[i].address;
>>>    		cpus[i].active = false;
>>> +		cpus[i].idx = i;
>>>    		/*
>>>    		 * Fill in the boot CPU. If the boot CPU is not at index 0,
>>>    		 * swap it with the one at index 0. This guarantees that the
>>
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-06-27 11:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-24 14:45 [kvm-unit-tests PATCH v2 0/3] better smp interrupt checks Claudio Imbrenda
2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 1/3] lib: s390x: add functions to set and clear PSW bits Claudio Imbrenda
2022-06-27  8:35   ` Janosch Frank
2022-06-27 10:47     ` Claudio Imbrenda
2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 2/3] s390x: skey.c: rework the interrupt handler Claudio Imbrenda
2022-06-24 14:45 ` [kvm-unit-tests PATCH v2 3/3] lib: s390x: better smp interrupt checks Claudio Imbrenda
2022-06-27  9:28   ` Janosch Frank
2022-06-27 10:53     ` Claudio Imbrenda
2022-06-27 11:09       ` Janosch Frank

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.