diff mbox series

[v6,03/20] xen/riscv: introduce extenstion support check by compiler

Message ID d4df95eb7a30df3f882b67f200964232fee9d6c1.1710517542.git.oleksii.kurochko@gmail.com (mailing list archive)
State Superseded
Headers show
Series Enable build of full Xen for RISC-V | expand

Commit Message

Oleksii Kurochko March 15, 2024, 6:05 p.m. UTC
Currently, RISC-V requires two extensions: _zbb and _zihintpause.

This patch introduces a compiler check to check if these extensions
are supported.
Additionally, it introduces the riscv/booting.txt file, which contains
information about the extensions that should be supported by the platform.

In the future, a feature will be introduced to check whether an extension
is supported at runtime.
However, this feature requires functionality for parsing device tree
source (DTS), which is not yet available.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - new patch for this patch series
---
 docs/misc/riscv/booting.txt | 16 ++++++++++++++++
 xen/arch/riscv/arch.mk      | 10 ++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 docs/misc/riscv/booting.txt

Comments

Jan Beulich March 18, 2024, 4:58 p.m. UTC | #1
On 15.03.2024 19:05, Oleksii Kurochko wrote:
> Currently, RISC-V requires two extensions: _zbb and _zihintpause.

Do we really require Zbb already?

> This patch introduces a compiler check to check if these extensions
> are supported.
> Additionally, it introduces the riscv/booting.txt file, which contains
> information about the extensions that should be supported by the platform.
> 
> In the future, a feature will be introduced to check whether an extension
> is supported at runtime.
> However, this feature requires functionality for parsing device tree
> source (DTS), which is not yet available.

Can't you query the CPU for its features?

> --- a/xen/arch/riscv/arch.mk
> +++ b/xen/arch/riscv/arch.mk
> @@ -3,16 +3,22 @@
>  
>  $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
>  
> -CFLAGS-$(CONFIG_RISCV_64) += -mabi=lp64
> +riscv-abi-$(CONFIG_RISCV_32) := -mabi=ilp32
> +riscv-abi-$(CONFIG_RISCV_64) := -mabi=lp64
>  
>  riscv-march-$(CONFIG_RISCV_ISA_RV64G) := rv64g
>  riscv-march-$(CONFIG_RISCV_ISA_C)       := $(riscv-march-y)c
>  
> +extensions := $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zbb,"",_zbb) \
> +              $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zihintpause,"pause",_zihintpause)

Imo you want another helper macro here, where all one needs to pass in is
the extension name (i.e. zbb and zihintpause as per above). That'll also
help with line length, I hope.

Jan
Oleksii Kurochko March 20, 2024, 6:58 p.m. UTC | #2
On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
> On 15.03.2024 19:05, Oleksii Kurochko wrote:
> > Currently, RISC-V requires two extensions: _zbb and _zihintpause.
> 
> Do we really require Zbb already?
After an introduction of Andrew C. patches [1] it is requited for
__builtin_ffs{l}

[1]
https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
> 
> > This patch introduces a compiler check to check if these extensions
> > are supported.
> > Additionally, it introduces the riscv/booting.txt file, which
> > contains
> > information about the extensions that should be supported by the
> > platform.
> > 
> > In the future, a feature will be introduced to check whether an
> > extension
> > is supported at runtime.
> > However, this feature requires functionality for parsing device
> > tree
> > source (DTS), which is not yet available.
> 
> Can't you query the CPU for its features?
I couldn't find such reg ( or SBI call ) in the spec.

SBI call sbi_probe_extension() exists, but it doesn't check for every
possible extension. As far as I understand it checks only for that one
which are present in SBI spec.

The most closest thing I see how to check that without dts is how it is
done in OpenSBI:
#define csr_read_allowed(csr_num, trap)				\
	({							\
	register ulong tinfo asm("a3") = (ulong)trap;		\
	register ulong ttmp asm("a4");				\
	register ulong mtvec = sbi_hart_expected_trap_addr();	\
	register ulong ret =
0;					\
	((struct sbi_trap_info *)(trap))->cause = 0;		\
	asm volatile(						\
		"add %[ttmp], %[tinfo],
zero\n"			\
		"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n"\
		"csrr %[ret],
%[csr]\n"				\
		"csrw " STR(CSR_MTVEC) ", %[mtvec]"		\
	    : [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo),	\
	      [ttmp] "+&r"(ttmp), [ret] "=&r" (ret)		\
	    : [csr] "i" (csr_num)				\
	    : "memory");					\
	ret;							\
	})							\
...
	/* Detect if hart supports stimecmp CSR(Sstc extension) */
	if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) {
		csr_read_allowed(CSR_STIMECMP, (unsigned long)&trap);
		if (!trap.cause)
			__sbi_hart_update_extension(hfeatures,
					SBI_HART_EXT_SSTC, true);
	}

~ Oleksii

> 
> > --- a/xen/arch/riscv/arch.mk
> > +++ b/xen/arch/riscv/arch.mk
> > @@ -3,16 +3,22 @@
> >  
> >  $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
> >  
> > -CFLAGS-$(CONFIG_RISCV_64) += -mabi=lp64
> > +riscv-abi-$(CONFIG_RISCV_32) := -mabi=ilp32
> > +riscv-abi-$(CONFIG_RISCV_64) := -mabi=lp64
> >  
> >  riscv-march-$(CONFIG_RISCV_ISA_RV64G) := rv64g
> >  riscv-march-$(CONFIG_RISCV_ISA_C)       := $(riscv-march-y)c
> >  
> > +extensions := $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-
> > march-y)_zbb,"",_zbb) \
> > +              $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-
> > march-y)_zihintpause,"pause",_zihintpause)
> 
> Imo you want another helper macro here, where all one needs to pass
> in is
> the extension name (i.e. zbb and zihintpause as per above). That'll
> also
> help with line length, I hope.
> 
> Jan
Conor Dooley March 20, 2024, 7:44 p.m. UTC | #3
On Wed, Mar 20, 2024 at 07:58:05PM +0100, Oleksii wrote:
> On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
> > On 15.03.2024 19:05, Oleksii Kurochko wrote:
> > > Currently, RISC-V requires two extensions: _zbb and _zihintpause.
> > 
> > Do we really require Zbb already?
> After an introduction of Andrew C. patches [1] it is requited for
> __builtin_ffs{l}
> 
> [1]
> https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
> > 
> > > This patch introduces a compiler check to check if these extensions
> > > are supported.
> > > Additionally, it introduces the riscv/booting.txt file, which
> > > contains
> > > information about the extensions that should be supported by the
> > > platform.
> > > 
> > > In the future, a feature will be introduced to check whether an
> > > extension
> > > is supported at runtime.
> > > However, this feature requires functionality for parsing device
> > > tree
> > > source (DTS), which is not yet available.
> > 
> > Can't you query the CPU for its features?
> I couldn't find such reg ( or SBI call ) in the spec.

There isn't.

> SBI call sbi_probe_extension() exists, but it doesn't check for every
> possible extension. As far as I understand it checks only for that one
> which are present in SBI spec.

Yeah, it only checks for SBI extensions, not ISA extensions.

> The most closest thing I see how to check that without dts is how it is
> done in OpenSBI:

IIRC this only "works" because the OpenSBI devs assume that there are no
non-normative behaviours and all CSRs have their ~God~ RVI defined
meanings. Reading a CSR to see if it traps is not behaviour you can really
rely on unless the platform claims to support Sstrict - but Sstrict you'd
have to detect from the DT so chicken and egg for you! It's one of these
new "extensions" from the profiles spec, so it doesn't even have support
in Linux's dt-bindings yet. Up to Xen devs if you guys want to make the
same assumptions as OpenSBI. Linux doesn't and when we discussed this
not too long ago on the U-Boot ML in the context of the rng CSR it was
also decided not to do make the assumption there either.

Personally I wonder if you can just apply the same policy here as you
did with Zbb in the other thread and assume that something with H will
have Zihintpause and leave implementing a "fake" pause as an exercise
for someone that introduces such a system?
If Jess is correct, and I do remember testing this, it's actually
"always" safe to call the pause instruction on CPUs where the extension
is not supported as it uses an encoding of fence that effectively makes
it a into a nop:
https://lore.kernel.org/linux-riscv/2E96A836-764D-4D07-AB79-3861B9CC2B1F@jrtc27.com/
At worst, that'd make cpu_relax() a nop if someone didn't meet that
requirement.

FWIW, Linux's cpu_relax() on RISC-V looks like:
	static inline void cpu_relax(void)
	{
	#ifdef __riscv_muldiv
		int dummy;
		/* In lieu of a halt instruction, induce a long-latency stall. */
		__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
	#endif
	
	#ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE
		/*
		 * Reduce instruction retirement.
		 * This assumes the PC changes.
		 */
		__asm__ __volatile__ ("pause");
	#else
		/* Encoding of the pause instruction */
		__asm__ __volatile__ (".4byte 0x100000F");
	#endif
		barrier();
	}

I figure having div is part of your base requirements, so maybe you can
just do something similar in the !zihintpause case if making that
extension a requirement is problematic? 
Doing that invalid div used to be conditional, but cpu_relax() is in the
vdso so the static branch it used to be gated with got removed and its
now unconditional. Probably that's not a constraint on Xen's cpu_relax()?

Oh ye, and we do the .4byte crap so that toolchain support wasn't needed
for Zihintpause given we are using it in exactly one place.

Cheers,
Conor.

> #define csr_read_allowed(csr_num, trap)				\
> 	({							\
> 	register ulong tinfo asm("a3") = (ulong)trap;		\
> 	register ulong ttmp asm("a4");				\
> 	register ulong mtvec = sbi_hart_expected_trap_addr();	\
> 	register ulong ret =
> 0;					\
> 	((struct sbi_trap_info *)(trap))->cause = 0;		\
> 	asm volatile(						\
> 		"add %[ttmp], %[tinfo],
> zero\n"			\
> 		"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n"\
> 		"csrr %[ret],
> %[csr]\n"				\
> 		"csrw " STR(CSR_MTVEC) ", %[mtvec]"		\
> 	    : [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo),	\
> 	      [ttmp] "+&r"(ttmp), [ret] "=&r" (ret)		\
> 	    : [csr] "i" (csr_num)				\
> 	    : "memory");					\
> 	ret;							\
> 	})							\
> ...
> 	/* Detect if hart supports stimecmp CSR(Sstc extension) */
> 	if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) {
> 		csr_read_allowed(CSR_STIMECMP, (unsigned long)&trap);
> 		if (!trap.cause)
> 			__sbi_hart_update_extension(hfeatures,
> 					SBI_HART_EXT_SSTC, true);
> 	}
Jan Beulich March 21, 2024, 8:31 a.m. UTC | #4
On 20.03.2024 20:44, Conor Dooley wrote:
> On Wed, Mar 20, 2024 at 07:58:05PM +0100, Oleksii wrote:
>> On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
>>> On 15.03.2024 19:05, Oleksii Kurochko wrote:
>>>> Currently, RISC-V requires two extensions: _zbb and _zihintpause.
>>>
>>> Do we really require Zbb already?
>> After an introduction of Andrew C. patches [1] it is requited for
>> __builtin_ffs{l}
>>
>> [1]
>> https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
>>>
>>>> This patch introduces a compiler check to check if these extensions
>>>> are supported.
>>>> Additionally, it introduces the riscv/booting.txt file, which
>>>> contains
>>>> information about the extensions that should be supported by the
>>>> platform.
>>>>
>>>> In the future, a feature will be introduced to check whether an
>>>> extension
>>>> is supported at runtime.
>>>> However, this feature requires functionality for parsing device
>>>> tree
>>>> source (DTS), which is not yet available.
>>>
>>> Can't you query the CPU for its features?
>> I couldn't find such reg ( or SBI call ) in the spec.
> 
> There isn't.
> 
>> SBI call sbi_probe_extension() exists, but it doesn't check for every
>> possible extension. As far as I understand it checks only for that one
>> which are present in SBI spec.
> 
> Yeah, it only checks for SBI extensions, not ISA extensions.

And there was never a consideration to add, at the architecture level,
some straightforward way for all layers of software to be able to
easily detect availability of extensions? I find the lack thereof
pretty surprising ...

Jan
Oleksii Kurochko March 21, 2024, 9:07 a.m. UTC | #5
On Wed, 2024-03-20 at 19:44 +0000, Conor Dooley wrote:
> IIRC this only "works" because the OpenSBI devs assume that there are
> no
> non-normative behaviours and all CSRs have their ~God~ RVI defined
> meanings. Reading a CSR to see if it traps is not behaviour you can
> really
> rely on unless the platform claims to support Sstrict - but Sstrict
> you'd
> have to detect from the DT so chicken and egg for you! It's one of
> these
> new "extensions" from the profiles spec, so it doesn't even have
> support
> in Linux's dt-bindings yet. Up to Xen devs if you guys want to make
> the
> same assumptions as OpenSBI. Linux doesn't and when we discussed this
> not too long ago on the U-Boot ML in the context of the rng CSR it
> was
> also decided not to do make the assumption there either.
> 
> Personally I wonder if you can just apply the same policy here as you
> did with Zbb in the other thread and assume that something with H
> will
> have Zihintpause and leave implementing a "fake" pause as an exercise
> for someone that introduces such a system?

If i understand you correctly, then it is done in this way now. Only
build time check is done, but it would be nice also have some runtime
check, and for now, for runtime the "check" is only exists in
booting.txt where it mentioned that Xen expects from CPU to support
some extenstions; otherwise "please implement the following functions".

Anyway, at the moment, the best one runtime check which we can provide
is detect availability of extensions from DT and what I mentioned in
commit message.

~ Oleksii
Conor Dooley March 21, 2024, 9:22 a.m. UTC | #6
On Thu, Mar 21, 2024 at 09:31:59AM +0100, Jan Beulich wrote:
> On 20.03.2024 20:44, Conor Dooley wrote:
> > On Wed, Mar 20, 2024 at 07:58:05PM +0100, Oleksii wrote:
> >> On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
> >>> On 15.03.2024 19:05, Oleksii Kurochko wrote:
> >>>> Currently, RISC-V requires two extensions: _zbb and _zihintpause.
> >>>
> >>> Do we really require Zbb already?
> >> After an introduction of Andrew C. patches [1] it is requited for
> >> __builtin_ffs{l}
> >>
> >> [1]
> >> https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
> >>>
> >>>> This patch introduces a compiler check to check if these extensions
> >>>> are supported.
> >>>> Additionally, it introduces the riscv/booting.txt file, which
> >>>> contains
> >>>> information about the extensions that should be supported by the
> >>>> platform.
> >>>>
> >>>> In the future, a feature will be introduced to check whether an
> >>>> extension
> >>>> is supported at runtime.
> >>>> However, this feature requires functionality for parsing device
> >>>> tree
> >>>> source (DTS), which is not yet available.
> >>>
> >>> Can't you query the CPU for its features?
> >> I couldn't find such reg ( or SBI call ) in the spec.
> > 
> > There isn't.
> > 
> >> SBI call sbi_probe_extension() exists, but it doesn't check for every
> >> possible extension. As far as I understand it checks only for that one
> >> which are present in SBI spec.
> > 
> > Yeah, it only checks for SBI extensions, not ISA extensions.
> 
> And there was never a consideration to add, at the architecture level,
> some straightforward way for all layers of software to be able to
> easily detect availability of extensions? I find the lack thereof
> pretty surprising ...

No, there sorta is. There's a "configuration structure" spec in the
works, but the (public?) documentation for it is very nascent:
https://github.com/riscv/configuration-structure/

It uses (what I seem to recall is an m-mode) CSR to give the address
of an ASN.1 structure in memory which is intended to encode a whole
raft of information. The CSR itself might be M-Mode, but that doesn't
prevent accessing the data itself at any layer in the stack. The last
time I read it I got the impression it was supposed to be usable for
describing an entire system (including things like i2c or spi
controllers). I don't think it ever explicitly says that in the spec,
but there's a note (IIRC) that mentions being unsuitable for describing
devices on dynamic buses like PCI, so that kinda implies anything else
is fair game.

Hope that helps?
diff mbox series

Patch

diff --git a/docs/misc/riscv/booting.txt b/docs/misc/riscv/booting.txt
new file mode 100644
index 0000000000..cb4d79f12c
--- /dev/null
+++ b/docs/misc/riscv/booting.txt
@@ -0,0 +1,16 @@ 
+System requirements
+===================
+
+The following extensions are expected to be supported by a system on which
+Xen is run:
+- Zbb:
+  RISC-V doesn't have a CLZ instruction in the base ISA.
+  As a consequence, __builtin_ffs() emits a library call to ffs() on GCC,
+  or a de Bruijn sequence on Clang.
+  Zbb extension adds a CLZ instruction, after which __builtin_ffs() emits
+  a very simple sequence.
+  The similar issue occurs with other __builtin_<bitop>, so it is needed to
+  provide a generic version of bitops in RISC-V bitops.h
+- Zihintpause:
+  On a system that doesn't have this extension, cpu_relax() should be
+  implemented properly.
diff --git a/xen/arch/riscv/arch.mk b/xen/arch/riscv/arch.mk
index 8403f96b6f..da6f8c82eb 100644
--- a/xen/arch/riscv/arch.mk
+++ b/xen/arch/riscv/arch.mk
@@ -3,16 +3,22 @@ 
 
 $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
 
-CFLAGS-$(CONFIG_RISCV_64) += -mabi=lp64
+riscv-abi-$(CONFIG_RISCV_32) := -mabi=ilp32
+riscv-abi-$(CONFIG_RISCV_64) := -mabi=lp64
 
 riscv-march-$(CONFIG_RISCV_ISA_RV64G) := rv64g
 riscv-march-$(CONFIG_RISCV_ISA_C)       := $(riscv-march-y)c
 
+extensions := $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zbb,"",_zbb) \
+              $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zihintpause,"pause",_zihintpause)
+
+extensions := $(subst $(space),,$(extensions))
+
 # Note that -mcmodel=medany is used so that Xen can be mapped
 # into the upper half _or_ the lower half of the address space.
 # -mcmodel=medlow would force Xen into the lower half.
 
-CFLAGS += -march=$(riscv-march-y) -mstrict-align -mcmodel=medany
+CFLAGS += $(riscv-abi-y) -march=$(riscv-march-y)$(extensions) -mstrict-align -mcmodel=medany
 
 # TODO: Drop override when more of the build is working
 override ALL_OBJS-y = arch/$(SRCARCH)/built_in.o