All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH 0/3] riscv: Improve on-cpu and IPI support
@ 2024-08-30 10:12 ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm-riscv

The first two patches improve general library support for cpumasks and
the on-cpus API. on-cpus can now take cpumasks for input. The last patch
improves support for sending IPIs on riscv using the SBI IPI extension
by supporting a nicer interface of cpuids and cpumasks.

Andrew Jones (3):
  lib/cpumask: Fix and simplify a few functions
  lib/on-cpus: Introduce on_cpumask and on_cpumask_async
  riscv: Introduce SBI IPI convenience functions

 lib/cpumask.h       | 47 +++++++++++++++++----------------------------
 lib/on-cpus.c       | 35 +++++++++++++++++++++++++--------
 lib/on-cpus.h       |  3 +++
 lib/riscv/asm/sbi.h |  3 +++
 lib/riscv/sbi.c     | 43 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 94 insertions(+), 37 deletions(-)

-- 
2.45.2



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

* [kvm-unit-tests PATCH 0/3] riscv: Improve on-cpu and IPI support
@ 2024-08-30 10:12 ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm, kvm-riscv; +Cc: atishp, cade.richard, jamestiotio

The first two patches improve general library support for cpumasks and
the on-cpus API. on-cpus can now take cpumasks for input. The last patch
improves support for sending IPIs on riscv using the SBI IPI extension
by supporting a nicer interface of cpuids and cpumasks.

Andrew Jones (3):
  lib/cpumask: Fix and simplify a few functions
  lib/on-cpus: Introduce on_cpumask and on_cpumask_async
  riscv: Introduce SBI IPI convenience functions

 lib/cpumask.h       | 47 +++++++++++++++++----------------------------
 lib/on-cpus.c       | 35 +++++++++++++++++++++++++--------
 lib/on-cpus.h       |  3 +++
 lib/riscv/asm/sbi.h |  3 +++
 lib/riscv/sbi.c     | 43 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 94 insertions(+), 37 deletions(-)

-- 
2.45.2


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

* [kvm-unit-tests PATCH 1/3] lib/cpumask: Fix and simplify a few functions
  2024-08-30 10:12 ` Andrew Jones
@ 2024-08-30 10:12   ` Andrew Jones
  -1 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm-riscv

Simplify cpumask_setall and cpumask_clear by just using memset. Also
simplify cpumask_empty and cpumask_full. This is a fix for
cpumask_empty as it would have reported non-empty for cpumasks that
had uninitialized junk following nr_cpus when nr_cpus < NR_CPUS.
There aren't currently any users of cpumask_empty though so that bug
has never appeared. cpumask_full was just convoluted and can now
follow cpumask_empty's new pattern. I've already yelled at a mirror
to scold the author of the original implementations!

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/cpumask.h | 47 ++++++++++++++++++-----------------------------
 1 file changed, 18 insertions(+), 29 deletions(-)

diff --git a/lib/cpumask.h b/lib/cpumask.h
index be1919234d8e..e1e92aacd1f1 100644
--- a/lib/cpumask.h
+++ b/lib/cpumask.h
@@ -6,8 +6,9 @@
  */
 #ifndef _CPUMASK_H_
 #define _CPUMASK_H_
-#include <asm/setup.h>
 #include <bitops.h>
+#include <limits.h>
+#include <asm/setup.h>
 
 #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
@@ -49,46 +50,34 @@ static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask)
 
 static inline void cpumask_setall(cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG)
-		cpumask_bits(mask)[BIT_WORD(i)] = ~0UL;
-	i -= BITS_PER_LONG;
-	if ((nr_cpus - i) < BITS_PER_LONG)
-		cpumask_bits(mask)[BIT_WORD(i)] = BIT_MASK(nr_cpus - i) - 1;
+	memset(mask, 0xff, sizeof(*mask));
 }
 
 static inline void cpumask_clear(cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG)
-		cpumask_bits(mask)[BIT_WORD(i)] = 0UL;
+	memset(mask, 0, sizeof(*mask));
 }
 
 static inline bool cpumask_empty(const cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG) {
-		if (i < NR_CPUS) { /* silence crazy compiler warning */
-			if (cpumask_bits(mask)[BIT_WORD(i)] != 0UL)
-				return false;
-		}
-	}
-	return true;
+	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
+
+	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
+		if (cpumask_bits(mask)[i])
+			return false;
+
+	return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask);
 }
 
 static inline bool cpumask_full(const cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG) {
-		if (cpumask_bits(mask)[BIT_WORD(i)] != ~0UL) {
-			if ((nr_cpus - i) >= BITS_PER_LONG)
-				return false;
-			if (cpumask_bits(mask)[BIT_WORD(i)]
-					!= BIT_MASK(nr_cpus - i) - 1)
-				return false;
-		}
-	}
-	return true;
+	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
+
+	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
+		if (cpumask_bits(mask)[i] != ULONG_MAX)
+			return false;
+
+	return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask;
 }
 
 static inline int cpumask_weight(const cpumask_t *mask)
-- 
2.45.2



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

* [kvm-unit-tests PATCH 1/3] lib/cpumask: Fix and simplify a few functions
@ 2024-08-30 10:12   ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm, kvm-riscv; +Cc: atishp, cade.richard, jamestiotio

Simplify cpumask_setall and cpumask_clear by just using memset. Also
simplify cpumask_empty and cpumask_full. This is a fix for
cpumask_empty as it would have reported non-empty for cpumasks that
had uninitialized junk following nr_cpus when nr_cpus < NR_CPUS.
There aren't currently any users of cpumask_empty though so that bug
has never appeared. cpumask_full was just convoluted and can now
follow cpumask_empty's new pattern. I've already yelled at a mirror
to scold the author of the original implementations!

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/cpumask.h | 47 ++++++++++++++++++-----------------------------
 1 file changed, 18 insertions(+), 29 deletions(-)

diff --git a/lib/cpumask.h b/lib/cpumask.h
index be1919234d8e..e1e92aacd1f1 100644
--- a/lib/cpumask.h
+++ b/lib/cpumask.h
@@ -6,8 +6,9 @@
  */
 #ifndef _CPUMASK_H_
 #define _CPUMASK_H_
-#include <asm/setup.h>
 #include <bitops.h>
+#include <limits.h>
+#include <asm/setup.h>
 
 #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
@@ -49,46 +50,34 @@ static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask)
 
 static inline void cpumask_setall(cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG)
-		cpumask_bits(mask)[BIT_WORD(i)] = ~0UL;
-	i -= BITS_PER_LONG;
-	if ((nr_cpus - i) < BITS_PER_LONG)
-		cpumask_bits(mask)[BIT_WORD(i)] = BIT_MASK(nr_cpus - i) - 1;
+	memset(mask, 0xff, sizeof(*mask));
 }
 
 static inline void cpumask_clear(cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG)
-		cpumask_bits(mask)[BIT_WORD(i)] = 0UL;
+	memset(mask, 0, sizeof(*mask));
 }
 
 static inline bool cpumask_empty(const cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG) {
-		if (i < NR_CPUS) { /* silence crazy compiler warning */
-			if (cpumask_bits(mask)[BIT_WORD(i)] != 0UL)
-				return false;
-		}
-	}
-	return true;
+	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
+
+	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
+		if (cpumask_bits(mask)[i])
+			return false;
+
+	return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask);
 }
 
 static inline bool cpumask_full(const cpumask_t *mask)
 {
-	int i;
-	for (i = 0; i < nr_cpus; i += BITS_PER_LONG) {
-		if (cpumask_bits(mask)[BIT_WORD(i)] != ~0UL) {
-			if ((nr_cpus - i) >= BITS_PER_LONG)
-				return false;
-			if (cpumask_bits(mask)[BIT_WORD(i)]
-					!= BIT_MASK(nr_cpus - i) - 1)
-				return false;
-		}
-	}
-	return true;
+	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
+
+	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
+		if (cpumask_bits(mask)[i] != ULONG_MAX)
+			return false;
+
+	return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask;
 }
 
 static inline int cpumask_weight(const cpumask_t *mask)
-- 
2.45.2


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

* [kvm-unit-tests PATCH 2/3] lib/on-cpus: Introduce on_cpumask and on_cpumask_async
  2024-08-30 10:12 ` Andrew Jones
@ 2024-08-30 10:12   ` Andrew Jones
  -1 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm-riscv

Provide functions to launch tasks on a selection of cpus identified
by a cpumask.

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/on-cpus.c | 35 +++++++++++++++++++++++++++--------
 lib/on-cpus.h |  3 +++
 2 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/lib/on-cpus.c b/lib/on-cpus.c
index aed70f7b27b2..892149338419 100644
--- a/lib/on-cpus.c
+++ b/lib/on-cpus.c
@@ -124,24 +124,32 @@ void on_cpu_async(int cpu, void (*func)(void *data), void *data)
 	smp_send_event();
 }
 
-void on_cpu(int cpu, void (*func)(void *data), void *data)
+void on_cpumask_async(const cpumask_t *mask, void (*func)(void *data), void *data)
 {
-	on_cpu_async(cpu, func, data);
-	cpu_wait(cpu);
+	int cpu, me = smp_processor_id();
+
+	for_each_cpu(cpu, mask) {
+		if (cpu == me)
+			continue;
+		on_cpu_async(cpu, func, data);
+	}
+	if (cpumask_test_cpu(me, mask))
+		func(data);
 }
 
-void on_cpus(void (*func)(void *data), void *data)
+void on_cpumask(const cpumask_t *mask, void (*func)(void *data), void *data)
 {
 	int cpu, me = smp_processor_id();
 
-	for_each_present_cpu(cpu) {
+	for_each_cpu(cpu, mask) {
 		if (cpu == me)
 			continue;
 		on_cpu_async(cpu, func, data);
 	}
-	func(data);
+	if (cpumask_test_cpu(me, mask))
+		func(data);
 
-	for_each_present_cpu(cpu) {
+	for_each_cpu(cpu, mask) {
 		if (cpu == me)
 			continue;
 		cpumask_set_cpu(me, &on_cpu_info[cpu].waiters);
@@ -149,6 +157,17 @@ void on_cpus(void (*func)(void *data), void *data)
 	}
 	while (cpumask_weight(&cpu_idle_mask) < nr_cpus - 1)
 		smp_wait_for_event();
-	for_each_present_cpu(cpu)
+	for_each_cpu(cpu, mask)
 		cpumask_clear_cpu(me, &on_cpu_info[cpu].waiters);
 }
+
+void on_cpu(int cpu, void (*func)(void *data), void *data)
+{
+	on_cpu_async(cpu, func, data);
+	cpu_wait(cpu);
+}
+
+void on_cpus(void (*func)(void *data), void *data)
+{
+	on_cpumask(&cpu_present_mask, func, data);
+}
diff --git a/lib/on-cpus.h b/lib/on-cpus.h
index 41103b0245c7..4bc6236d6b58 100644
--- a/lib/on-cpus.h
+++ b/lib/on-cpus.h
@@ -2,6 +2,7 @@
 #ifndef _ON_CPUS_H_
 #define _ON_CPUS_H_
 #include <stdbool.h>
+#include <cpumask.h>
 
 extern bool cpu0_calls_idle;
 
@@ -10,5 +11,7 @@ void do_idle(void);
 void on_cpu_async(int cpu, void (*func)(void *data), void *data);
 void on_cpu(int cpu, void (*func)(void *data), void *data);
 void on_cpus(void (*func)(void *data), void *data);
+void on_cpumask_async(const cpumask_t *mask, void (*func)(void *data), void *data);
+void on_cpumask(const cpumask_t *mask, void (*func)(void *data), void *data);
 
 #endif /* _ON_CPUS_H_ */
-- 
2.45.2



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

* [kvm-unit-tests PATCH 2/3] lib/on-cpus: Introduce on_cpumask and on_cpumask_async
@ 2024-08-30 10:12   ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm, kvm-riscv; +Cc: atishp, cade.richard, jamestiotio

Provide functions to launch tasks on a selection of cpus identified
by a cpumask.

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/on-cpus.c | 35 +++++++++++++++++++++++++++--------
 lib/on-cpus.h |  3 +++
 2 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/lib/on-cpus.c b/lib/on-cpus.c
index aed70f7b27b2..892149338419 100644
--- a/lib/on-cpus.c
+++ b/lib/on-cpus.c
@@ -124,24 +124,32 @@ void on_cpu_async(int cpu, void (*func)(void *data), void *data)
 	smp_send_event();
 }
 
-void on_cpu(int cpu, void (*func)(void *data), void *data)
+void on_cpumask_async(const cpumask_t *mask, void (*func)(void *data), void *data)
 {
-	on_cpu_async(cpu, func, data);
-	cpu_wait(cpu);
+	int cpu, me = smp_processor_id();
+
+	for_each_cpu(cpu, mask) {
+		if (cpu == me)
+			continue;
+		on_cpu_async(cpu, func, data);
+	}
+	if (cpumask_test_cpu(me, mask))
+		func(data);
 }
 
-void on_cpus(void (*func)(void *data), void *data)
+void on_cpumask(const cpumask_t *mask, void (*func)(void *data), void *data)
 {
 	int cpu, me = smp_processor_id();
 
-	for_each_present_cpu(cpu) {
+	for_each_cpu(cpu, mask) {
 		if (cpu == me)
 			continue;
 		on_cpu_async(cpu, func, data);
 	}
-	func(data);
+	if (cpumask_test_cpu(me, mask))
+		func(data);
 
-	for_each_present_cpu(cpu) {
+	for_each_cpu(cpu, mask) {
 		if (cpu == me)
 			continue;
 		cpumask_set_cpu(me, &on_cpu_info[cpu].waiters);
@@ -149,6 +157,17 @@ void on_cpus(void (*func)(void *data), void *data)
 	}
 	while (cpumask_weight(&cpu_idle_mask) < nr_cpus - 1)
 		smp_wait_for_event();
-	for_each_present_cpu(cpu)
+	for_each_cpu(cpu, mask)
 		cpumask_clear_cpu(me, &on_cpu_info[cpu].waiters);
 }
+
+void on_cpu(int cpu, void (*func)(void *data), void *data)
+{
+	on_cpu_async(cpu, func, data);
+	cpu_wait(cpu);
+}
+
+void on_cpus(void (*func)(void *data), void *data)
+{
+	on_cpumask(&cpu_present_mask, func, data);
+}
diff --git a/lib/on-cpus.h b/lib/on-cpus.h
index 41103b0245c7..4bc6236d6b58 100644
--- a/lib/on-cpus.h
+++ b/lib/on-cpus.h
@@ -2,6 +2,7 @@
 #ifndef _ON_CPUS_H_
 #define _ON_CPUS_H_
 #include <stdbool.h>
+#include <cpumask.h>
 
 extern bool cpu0_calls_idle;
 
@@ -10,5 +11,7 @@ void do_idle(void);
 void on_cpu_async(int cpu, void (*func)(void *data), void *data);
 void on_cpu(int cpu, void (*func)(void *data), void *data);
 void on_cpus(void (*func)(void *data), void *data);
+void on_cpumask_async(const cpumask_t *mask, void (*func)(void *data), void *data);
+void on_cpumask(const cpumask_t *mask, void (*func)(void *data), void *data);
 
 #endif /* _ON_CPUS_H_ */
-- 
2.45.2


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

* [kvm-unit-tests PATCH 3/3] riscv: Introduce SBI IPI convenience functions
  2024-08-30 10:12 ` Andrew Jones
@ 2024-08-30 10:12   ` Andrew Jones
  -1 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm-riscv

The SBI IPI function interface is a bit painful to use since it
operates on hartids as opposed to cpuids and requires determining a
mask base and a mask. Provide functions allowing IPIs to be sent to
single cpus and to all cpus set in a cpumask in order to simplify
things for unit tests.

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/riscv/asm/sbi.h |  3 +++
 lib/riscv/sbi.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h
index 4a35cf38da70..e032444dd760 100644
--- a/lib/riscv/asm/sbi.h
+++ b/lib/riscv/asm/sbi.h
@@ -13,6 +13,7 @@
 #define SBI_ERR_ALREADY_STOPPED		-8
 
 #ifndef __ASSEMBLY__
+#include <cpumask.h>
 
 enum sbi_ext_id {
 	SBI_EXT_BASE = 0x10,
@@ -67,6 +68,8 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
 void sbi_shutdown(void);
 struct sbiret sbi_hart_start(unsigned long hartid, unsigned long entry, unsigned long sp);
 struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base);
+struct sbiret sbi_send_ipi_cpu(int cpu);
+struct sbiret sbi_send_ipi_cpumask(const cpumask_t *mask);
 struct sbiret sbi_set_timer(unsigned long stime_value);
 long sbi_probe(int ext);
 
diff --git a/lib/riscv/sbi.c b/lib/riscv/sbi.c
index 07660e422cbb..ecc63acdebb7 100644
--- a/lib/riscv/sbi.c
+++ b/lib/riscv/sbi.c
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <libcflat.h>
+#include <cpumask.h>
+#include <limits.h>
 #include <asm/sbi.h>
+#include <asm/setup.h>
 
 struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
 			unsigned long arg1, unsigned long arg2,
@@ -44,6 +47,46 @@ struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base
 	return sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, hart_mask, hart_mask_base, 0, 0, 0, 0);
 }
 
+struct sbiret sbi_send_ipi_cpu(int cpu)
+{
+	return sbi_send_ipi(1UL, cpus[cpu].hartid);
+}
+
+struct sbiret sbi_send_ipi_cpumask(const cpumask_t *mask)
+{
+	struct sbiret ret;
+	cpumask_t tmp;
+
+	if (cpumask_full(mask))
+		return sbi_send_ipi(0, -1UL);
+
+	cpumask_copy(&tmp, mask);
+
+	while (!cpumask_empty(&tmp)) {
+		unsigned long base = ULONG_MAX;
+		unsigned long mask = 0;
+		int cpu;
+
+		for_each_cpu(cpu, &tmp) {
+			if (base > cpus[cpu].hartid)
+				base = cpus[cpu].hartid;
+		}
+
+		for_each_cpu(cpu, &tmp) {
+			if (cpus[cpu].hartid < base + BITS_PER_LONG) {
+				mask |= 1UL << (cpus[cpu].hartid - base);
+				cpumask_clear_cpu(cpu, &tmp);
+			}
+		}
+
+		ret = sbi_send_ipi(mask, base);
+		if (ret.error)
+			break;
+	}
+
+	return ret;
+}
+
 struct sbiret sbi_set_timer(unsigned long stime_value)
 {
 	return sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, 0, 0, 0, 0);
-- 
2.45.2



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

* [kvm-unit-tests PATCH 3/3] riscv: Introduce SBI IPI convenience functions
@ 2024-08-30 10:12   ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 10:12 UTC (permalink / raw)
  To: kvm, kvm-riscv; +Cc: atishp, cade.richard, jamestiotio

The SBI IPI function interface is a bit painful to use since it
operates on hartids as opposed to cpuids and requires determining a
mask base and a mask. Provide functions allowing IPIs to be sent to
single cpus and to all cpus set in a cpumask in order to simplify
things for unit tests.

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/riscv/asm/sbi.h |  3 +++
 lib/riscv/sbi.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h
index 4a35cf38da70..e032444dd760 100644
--- a/lib/riscv/asm/sbi.h
+++ b/lib/riscv/asm/sbi.h
@@ -13,6 +13,7 @@
 #define SBI_ERR_ALREADY_STOPPED		-8
 
 #ifndef __ASSEMBLY__
+#include <cpumask.h>
 
 enum sbi_ext_id {
 	SBI_EXT_BASE = 0x10,
@@ -67,6 +68,8 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
 void sbi_shutdown(void);
 struct sbiret sbi_hart_start(unsigned long hartid, unsigned long entry, unsigned long sp);
 struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base);
+struct sbiret sbi_send_ipi_cpu(int cpu);
+struct sbiret sbi_send_ipi_cpumask(const cpumask_t *mask);
 struct sbiret sbi_set_timer(unsigned long stime_value);
 long sbi_probe(int ext);
 
diff --git a/lib/riscv/sbi.c b/lib/riscv/sbi.c
index 07660e422cbb..ecc63acdebb7 100644
--- a/lib/riscv/sbi.c
+++ b/lib/riscv/sbi.c
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <libcflat.h>
+#include <cpumask.h>
+#include <limits.h>
 #include <asm/sbi.h>
+#include <asm/setup.h>
 
 struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
 			unsigned long arg1, unsigned long arg2,
@@ -44,6 +47,46 @@ struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base
 	return sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, hart_mask, hart_mask_base, 0, 0, 0, 0);
 }
 
+struct sbiret sbi_send_ipi_cpu(int cpu)
+{
+	return sbi_send_ipi(1UL, cpus[cpu].hartid);
+}
+
+struct sbiret sbi_send_ipi_cpumask(const cpumask_t *mask)
+{
+	struct sbiret ret;
+	cpumask_t tmp;
+
+	if (cpumask_full(mask))
+		return sbi_send_ipi(0, -1UL);
+
+	cpumask_copy(&tmp, mask);
+
+	while (!cpumask_empty(&tmp)) {
+		unsigned long base = ULONG_MAX;
+		unsigned long mask = 0;
+		int cpu;
+
+		for_each_cpu(cpu, &tmp) {
+			if (base > cpus[cpu].hartid)
+				base = cpus[cpu].hartid;
+		}
+
+		for_each_cpu(cpu, &tmp) {
+			if (cpus[cpu].hartid < base + BITS_PER_LONG) {
+				mask |= 1UL << (cpus[cpu].hartid - base);
+				cpumask_clear_cpu(cpu, &tmp);
+			}
+		}
+
+		ret = sbi_send_ipi(mask, base);
+		if (ret.error)
+			break;
+	}
+
+	return ret;
+}
+
 struct sbiret sbi_set_timer(unsigned long stime_value)
 {
 	return sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, 0, 0, 0, 0);
-- 
2.45.2


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

* [kvm-unit-tests PATCH 4/3] riscv: Provide helpers for IPIs
  2024-08-30 10:12 ` Andrew Jones
@ 2024-08-30 11:01   ` Andrew Jones
  -1 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 11:01 UTC (permalink / raw)
  To: kvm-riscv

Provide a few functions to enable/disable/acknowledge IPIs.

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/riscv/asm/csr.h       |  3 ++-
 lib/riscv/asm/processor.h | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/lib/riscv/asm/csr.h b/lib/riscv/asm/csr.h
index 24b333e02589..16f5ddd762de 100644
--- a/lib/riscv/asm/csr.h
+++ b/lib/riscv/asm/csr.h
@@ -51,7 +51,8 @@
 #define IRQ_S_GEXT		12
 #define IRQ_PMU_OVF		13
 
-#define IE_TIE			(_AC(0x1, UL) << IRQ_S_TIMER)
+#define IE_SSIE			(_AC(1, UL) << IRQ_S_SOFT)
+#define IE_TIE			(_AC(1, UL) << IRQ_S_TIMER)
 
 #define IP_TIP			IE_TIE
 
diff --git a/lib/riscv/asm/processor.h b/lib/riscv/asm/processor.h
index 4c9ad968460d..8989d8d686f9 100644
--- a/lib/riscv/asm/processor.h
+++ b/lib/riscv/asm/processor.h
@@ -32,6 +32,21 @@ static inline void local_irq_disable(void)
 	csr_clear(CSR_SSTATUS, SR_SIE);
 }
 
+static inline void local_ipi_enable(void)
+{
+	csr_set(CSR_SIE, IE_SSIE);
+}
+
+static inline void local_ipi_disable(void)
+{
+	csr_clear(CSR_SIE, IE_SSIE);
+}
+
+static inline void ipi_ack(void)
+{
+	csr_clear(CSR_SIP, IE_SSIE);
+}
+
 void install_exception_handler(unsigned long cause, void (*handler)(struct pt_regs *));
 void install_irq_handler(unsigned long cause, void (*handler)(struct pt_regs *));
 void do_handle_exception(struct pt_regs *regs);
-- 
2.45.2



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

* [kvm-unit-tests PATCH 4/3] riscv: Provide helpers for IPIs
@ 2024-08-30 11:01   ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-08-30 11:01 UTC (permalink / raw)
  To: kvm, kvm-riscv; +Cc: atishp, cade.richard, jamestiotio

Provide a few functions to enable/disable/acknowledge IPIs.

Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
 lib/riscv/asm/csr.h       |  3 ++-
 lib/riscv/asm/processor.h | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/lib/riscv/asm/csr.h b/lib/riscv/asm/csr.h
index 24b333e02589..16f5ddd762de 100644
--- a/lib/riscv/asm/csr.h
+++ b/lib/riscv/asm/csr.h
@@ -51,7 +51,8 @@
 #define IRQ_S_GEXT		12
 #define IRQ_PMU_OVF		13
 
-#define IE_TIE			(_AC(0x1, UL) << IRQ_S_TIMER)
+#define IE_SSIE			(_AC(1, UL) << IRQ_S_SOFT)
+#define IE_TIE			(_AC(1, UL) << IRQ_S_TIMER)
 
 #define IP_TIP			IE_TIE
 
diff --git a/lib/riscv/asm/processor.h b/lib/riscv/asm/processor.h
index 4c9ad968460d..8989d8d686f9 100644
--- a/lib/riscv/asm/processor.h
+++ b/lib/riscv/asm/processor.h
@@ -32,6 +32,21 @@ static inline void local_irq_disable(void)
 	csr_clear(CSR_SSTATUS, SR_SIE);
 }
 
+static inline void local_ipi_enable(void)
+{
+	csr_set(CSR_SIE, IE_SSIE);
+}
+
+static inline void local_ipi_disable(void)
+{
+	csr_clear(CSR_SIE, IE_SSIE);
+}
+
+static inline void ipi_ack(void)
+{
+	csr_clear(CSR_SIP, IE_SSIE);
+}
+
 void install_exception_handler(unsigned long cause, void (*handler)(struct pt_regs *));
 void install_irq_handler(unsigned long cause, void (*handler)(struct pt_regs *));
 void do_handle_exception(struct pt_regs *regs);
-- 
2.45.2


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

* [kvm-unit-tests PATCH 0/3] riscv: Improve on-cpu and IPI support
  2024-08-30 10:12 ` Andrew Jones
@ 2024-09-03 13:41   ` Andrew Jones
  -1 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-09-03 13:41 UTC (permalink / raw)
  To: kvm-riscv

On Fri, Aug 30, 2024 at 12:12:22PM GMT, Andrew Jones wrote:
> The first two patches improve general library support for cpumasks and
> the on-cpus API. on-cpus can now take cpumasks for input. The last patch
> improves support for sending IPIs on riscv using the SBI IPI extension
> by supporting a nicer interface of cpuids and cpumasks.
> 
> Andrew Jones (3):
>   lib/cpumask: Fix and simplify a few functions
>   lib/on-cpus: Introduce on_cpumask and on_cpumask_async
>   riscv: Introduce SBI IPI convenience functions
> 
>  lib/cpumask.h       | 47 +++++++++++++++++----------------------------
>  lib/on-cpus.c       | 35 +++++++++++++++++++++++++--------
>  lib/on-cpus.h       |  3 +++
>  lib/riscv/asm/sbi.h |  3 +++
>  lib/riscv/sbi.c     | 43 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 94 insertions(+), 37 deletions(-)
> 
> -- 
> 2.45.2

Queued on riscv/sbi, https://gitlab.com/jones-drew/kvm-unit-tests/-/commits/riscv%2Fsbi


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

* Re: [kvm-unit-tests PATCH 0/3] riscv: Improve on-cpu and IPI support
@ 2024-09-03 13:41   ` Andrew Jones
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Jones @ 2024-09-03 13:41 UTC (permalink / raw)
  To: kvm, kvm-riscv; +Cc: atishp, cade.richard, jamestiotio

On Fri, Aug 30, 2024 at 12:12:22PM GMT, Andrew Jones wrote:
> The first two patches improve general library support for cpumasks and
> the on-cpus API. on-cpus can now take cpumasks for input. The last patch
> improves support for sending IPIs on riscv using the SBI IPI extension
> by supporting a nicer interface of cpuids and cpumasks.
> 
> Andrew Jones (3):
>   lib/cpumask: Fix and simplify a few functions
>   lib/on-cpus: Introduce on_cpumask and on_cpumask_async
>   riscv: Introduce SBI IPI convenience functions
> 
>  lib/cpumask.h       | 47 +++++++++++++++++----------------------------
>  lib/on-cpus.c       | 35 +++++++++++++++++++++++++--------
>  lib/on-cpus.h       |  3 +++
>  lib/riscv/asm/sbi.h |  3 +++
>  lib/riscv/sbi.c     | 43 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 94 insertions(+), 37 deletions(-)
> 
> -- 
> 2.45.2

Queued on riscv/sbi, https://gitlab.com/jones-drew/kvm-unit-tests/-/commits/riscv%2Fsbi

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

end of thread, other threads:[~2024-09-03 13:41 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-30 10:12 [kvm-unit-tests PATCH 0/3] riscv: Improve on-cpu and IPI support Andrew Jones
2024-08-30 10:12 ` Andrew Jones
2024-08-30 10:12 ` [kvm-unit-tests PATCH 1/3] lib/cpumask: Fix and simplify a few functions Andrew Jones
2024-08-30 10:12   ` Andrew Jones
2024-08-30 10:12 ` [kvm-unit-tests PATCH 2/3] lib/on-cpus: Introduce on_cpumask and on_cpumask_async Andrew Jones
2024-08-30 10:12   ` Andrew Jones
2024-08-30 10:12 ` [kvm-unit-tests PATCH 3/3] riscv: Introduce SBI IPI convenience functions Andrew Jones
2024-08-30 10:12   ` Andrew Jones
2024-08-30 11:01 ` [kvm-unit-tests PATCH 4/3] riscv: Provide helpers for IPIs Andrew Jones
2024-08-30 11:01   ` Andrew Jones
2024-09-03 13:41 ` [kvm-unit-tests PATCH 0/3] riscv: Improve on-cpu and IPI support Andrew Jones
2024-09-03 13:41   ` Andrew Jones

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.