Unverified Commit 5ee121a3 authored by Palmer Dabbelt's avatar Palmer Dabbelt
Browse files

Merge patch series "riscv: Apply Zawrs when available"

Andrew Jones <ajones@ventanamicro.com> says:

Zawrs provides two instructions (wrs.nto and wrs.sto), where both are
meant to allow the hart to enter a low-power state while waiting on a
store to a memory location. The instructions also both wait an
implementation-defined "short" duration (unless the implementation
terminates the stall for another reason). The difference is that while
wrs.sto will terminate when the duration elapses, wrs.nto, depending on
configuration, will either just keep waiting or an ILL exception will be
raised. Linux will use wrs.nto, so if platforms have an implementation
which falls in the "just keep waiting" category (which is not expected),
then it should _not_ advertise Zawrs in the hardware description.

Like wfi (and with the same {m,h}status bits to configure it), when
wrs.nto is configured to raise exceptions it's expected that the higher
privilege level will see the instruction was a wait instruction, do
something, and then resume execution following the instruction. For
example, KVM does configure exceptions for wfi (hstatus.VTW=1) and
therefore also for wrs.nto. KVM does this for wfi since it's better to
allow other tasks to be scheduled while a VCPU waits for an interrupt.
For waits such as those where wrs.nto/sto would be used, which are
typically locks, it is also a good idea for KVM to be involved, as it
can attempt to schedule the lock holding VCPU.

This series starts with Christoph's addition of the riscv
smp_cond_load_relaxed function which applies wrs.sto when available.
That patch has been reworked to use wrs.nto and to use the same approach
as Arm for the wait loop, since we can't have arbitrary C code between
the load-reserved and the wrs. Then, hwprobe support is added (since the
instructions are also usable from usermode), and finally KVM is
taught about wrs.nto, allowing guests to see and use the Zawrs
extension.

We still don't have test results from hardware, and it's not possible to
prove that using Zawrs is a win when testing on QEMU, not even when
oversubscribing VCPUs to guests. However, it is possible to use KVM
selftests to force a scenario where we can prove Zawrs does its job and
does it well. [4] is a test which does this and, on my machine, without
Zawrs it takes 16 seconds to complete and with Zawrs it takes 0.25
seconds.

This series is also available here [1]. In order to use QEMU for testing
a build with [2] is needed. In order to enable guests to use Zawrs with
KVM using kvmtool, the branch at [3] may be used.

[1] https://github.com/jones-drew/linux/commits/riscv/zawrs-v3/
[2] https://lore.kernel.org/all/20240312152901.512001-2-ajones@ventanamicro.com/
[3] https://github.com/jones-drew/kvmtool/commits/riscv/zawrs/
[4] https://github.com/jones-drew/linux/commit/cb2beccebcece10881db842ed69bdd5715cfab5d

Link: https://lore.kernel.org/r/20240426100820.14762-8-ajones@ventanamicro.com



* b4-shazam-merge:
  KVM: riscv: selftests: Add Zawrs extension to get-reg-list test
  KVM: riscv: Support guest wrs.nto
  riscv: hwprobe: export Zawrs ISA extension
  riscv: Add Zawrs support for spinlocks
  dt-bindings: riscv: Add Zawrs ISA extension description
  riscv: Provide a definition for 'pause'

Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents c9b8cd13 f2c43c61
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -235,6 +235,10 @@ The following keys are defined:
       supported as defined in the RISC-V ISA manual starting from commit
       c732a4f39a4 ("Zcmop is ratified/1.0").

  * :c:macro:`RISCV_HWPROBE_EXT_ZAWRS`: The Zawrs extension is supported as
       ratified in commit 98918c844281 ("Merge pull request #1217 from
       riscv/zawrs") of riscv-isa-manual.

* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
  information about the selected set of processors.

+7 −0
Original line number Diff line number Diff line
@@ -177,6 +177,13 @@ properties:
            is supported as ratified at commit 5059e0ca641c ("update to
            ratified") of the riscv-zacas.

        - const: zawrs
          description: |
            The Zawrs extension for entering a low-power state or for trapping
            to a hypervisor while waiting on a store to a memory location, as
            ratified in commit 98918c844281 ("Merge pull request #1217 from
            riscv/zawrs") of riscv-isa-manual.

        - const: zba
          description: |
            The standard Zba bit-manipulation extension for address generation
+13 −7
Original line number Diff line number Diff line
@@ -600,6 +600,19 @@ config RISCV_ISA_V_PREEMPTIVE
	  preemption. Enabling this config will result in higher memory
	  consumption due to the allocation of per-task's kernel Vector context.

config RISCV_ISA_ZAWRS
	bool "Zawrs extension support for more efficient busy waiting"
	depends on RISCV_ALTERNATIVE
	default y
	help
	  The Zawrs extension defines instructions to be used in polling loops
	  which allow a hart to enter a low-power state or to trap to the
	  hypervisor while waiting on a store to a memory location. Enable the
	  use of these instructions in the kernel when the Zawrs extension is
	  detected at boot.

	  If you don't know what to do here, say Y.

config TOOLCHAIN_HAS_ZBB
	bool
	default y
@@ -682,13 +695,6 @@ config RISCV_ISA_ZICBOZ

	   If you don't know what to do here, say Y.

config TOOLCHAIN_HAS_ZIHINTPAUSE
	bool
	default y
	depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zihintpause)
	depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zihintpause)
	depends on LLD_VERSION >= 150000 || LD_VERSION >= 23600

config TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
	def_bool y
	# https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aed44286efa8ae8717a77d94b51ac3614e2ca6dc
+0 −3
Original line number Diff line number Diff line
@@ -82,9 +82,6 @@ else
riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei
endif

# Check if the toolchain supports Zihintpause extension
riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE) := $(riscv-march-y)_zihintpause

# Remove F,D,V from isa string for all. Keep extensions between "fd" and "v" by
# matching non-v and non-multi-letter extensions out with the filter ([^v_]*)
KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/')
+30 −15
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#define _ASM_RISCV_BARRIER_H

#ifndef __ASSEMBLY__
#include <asm/cmpxchg.h>
#include <asm/fence.h>

#define nop()		__asm__ __volatile__ ("nop")
@@ -28,21 +29,6 @@
#define __smp_rmb()	RISCV_FENCE(r, r)
#define __smp_wmb()	RISCV_FENCE(w, w)

#define __smp_store_release(p, v)					\
do {									\
	compiletime_assert_atomic_type(*p);				\
	RISCV_FENCE(rw, w);						\
	WRITE_ONCE(*p, v);						\
} while (0)

#define __smp_load_acquire(p)						\
({									\
	typeof(*p) ___p1 = READ_ONCE(*p);				\
	compiletime_assert_atomic_type(*p);				\
	RISCV_FENCE(r, rw);						\
	___p1;								\
})

/*
 * This is a very specific barrier: it's currently only used in two places in
 * the kernel, both in the scheduler.  See include/linux/spinlock.h for the two
@@ -70,6 +56,35 @@ do { \
 */
#define smp_mb__after_spinlock()	RISCV_FENCE(iorw, iorw)

#define __smp_store_release(p, v)					\
do {									\
	compiletime_assert_atomic_type(*p);				\
	RISCV_FENCE(rw, w);						\
	WRITE_ONCE(*p, v);						\
} while (0)

#define __smp_load_acquire(p)						\
({									\
	typeof(*p) ___p1 = READ_ONCE(*p);				\
	compiletime_assert_atomic_type(*p);				\
	RISCV_FENCE(r, rw);						\
	___p1;								\
})

#ifdef CONFIG_RISCV_ISA_ZAWRS
#define smp_cond_load_relaxed(ptr, cond_expr) ({			\
	typeof(ptr) __PTR = (ptr);					\
	__unqual_scalar_typeof(*ptr) VAL;				\
	for (;;) {							\
		VAL = READ_ONCE(*__PTR);				\
		if (cond_expr)						\
			break;						\
		__cmpwait_relaxed(ptr, VAL);				\
	}								\
	(typeof(*ptr))VAL;						\
})
#endif

#include <asm-generic/barrier.h>

#endif /* __ASSEMBLY__ */
Loading